0029979: Data Exchange - Crash by reading STEP file
[occt.git] / adm / genproj.tcl
1 # =======================================================================
2 # Created on: 2014-07-24
3 # Created by: SKI
4 # Copyright (c) 2014 OPEN CASCADE SAS
5 #
6 # This file is part of Open CASCADE Technology software library.
7 #
8 # This library is free software; you can redistribute it and/or modify it under
9 # the terms of the GNU Lesser General Public License version 2.1 as published
10 # by the Free Software Foundation, with special exception defined in the file
11 # OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 # distribution for complete text of the license and disclaimer of any warranty.
13 #
14 # Alternatively, this file may be used under the terms of Open CASCADE
15 # commercial license or contractual agreement.
16
17 # =======================================================================
18 # This script defines Tcl command genproj generating project files for 
19 # different IDEs and platforms. Run it with -help to get synopsis.
20 # =======================================================================
21
22 source [file join [file dirname [info script]] genconfdeps.tcl]
23
24 # the script is assumed to be run from CASROOT (or dependent Products root)
25 set path [file normalize .]
26 set THE_CASROOT ""
27 set fBranch ""
28 if { [info exists ::env(CASROOT)] } {
29   set THE_CASROOT [file normalize "$::env(CASROOT)"]
30 }
31
32 proc _get_options { platform type branch } {
33   set res ""
34   if {[file exists "$::THE_CASROOT/adm/CMPLRS"]} {
35     set fd [open "$::THE_CASROOT/adm/CMPLRS" rb]
36     set opts [split [read $fd] "\n"]
37     close $fd
38     foreach line $opts {
39       if {[regexp "^${platform} ${type} ${branch} (.+)$" $line dummy res]} {
40         while {[regexp {\(([^\(\)]+) ([^\(\)]+) ([^\(\)]+)\)(.+)} $res dummy p t b oldres]} {
41           set res "[_get_options $p $t $b] $oldres"
42         }
43       }
44     }
45   }
46   return $res
47 }
48
49 proc _get_type { name } {
50   set UDLIST {}
51   if {[file exists "$::path/adm/UDLIST"]} {
52     set fd [open "$::path/adm/UDLIST" rb]
53     set UDLIST [concat $UDLIST [split [read $fd] "\n"]]
54     close $fd
55   }
56   if { "$::path/adm/UDLIST" != "$::THE_CASROOT/adm/UDLIST" && [file exists "$::THE_CASROOT/adm/UDLIST"] } {
57     set fd [open "$::THE_CASROOT/adm/UDLIST" rb]
58     set UDLIST [concat $UDLIST [split [read $fd] "\n"]]
59     close $fd
60   }
61
62   foreach uitem $UDLIST {
63     set line [split $uitem]
64     if {[lindex $line 1] == "$name"} {
65       return [lindex $line 0]
66     }
67   }
68   return ""
69 }
70
71 proc _get_used_files { pk {inc true} {src true} } {
72   global path
73   set type [_get_type $pk]
74   set lret {}
75   set pk_path  "$path/src/$pk"
76   set FILES_path "$path/src/$pk/FILES"
77   set FILES {}
78   if {[file exists $FILES_path]} {
79     set fd [open $FILES_path rb]
80     set FILES [split [read $fd] "\n"]
81     close $fd
82   }
83   set FILES [lsearch -inline -all -not -exact $FILES ""]
84
85   set index -1
86   foreach line $FILES {
87     incr index
88     if {$inc && ([regexp {([^:\s]*\.[hgl]xx)$} $line dummy name] || [regexp {([^:\s]*\.h)$} $line dummy name]) && [file exists $pk_path/$name]} {
89       lappend lret "pubinclude $name $pk_path/$name"
90       continue
91     }
92     if {[regexp {:} $line]} {
93       regexp {[^:]*:+([^\s]*)} $line dummy line
94     }
95     regexp {([^\s]*)} $line dummy line
96     if {$src && [file exists $pk_path/$line]} {
97       lappend lret "source $line $pk_path/$line"
98     }
99   }
100   return $lret
101 }
102
103 # return location of the path within src directory
104 proc osutils:findSrcSubPath {theSubPath} {
105   if {[file exists "$::path/src/$theSubPath"]} {
106     return "$::path/src/$theSubPath"
107   }
108   return "$::THE_CASROOT/src/$theSubPath"
109 }
110
111 # Auxiliary tool comparing content of two files line-by-line.
112 proc osutils:isEqualContent { theContent1 theContent2 } {
113   set aLen1 [llength $theContent1]
114   set aLen2 [llength $theContent2]
115   if { $aLen1 != $aLen2 } {
116     return false
117   }
118
119   for {set aLineIter 0} {$aLineIter < $aLen1} {incr aLineIter} {
120     set aLine1 [lindex $theContent1 $aLineIter]
121     set aLine2 [lindex $theContent2 $aLineIter]
122     if { $aLine1 != $aLine2 } {
123       return false
124     }
125   }
126   return true
127 }
128
129 # Auxiliary function for writing new file content only if it has been actually changed
130 # (e.g. to preserve file timestamp on no change).
131 # Useful for automatically (re)generated files.
132 proc osutils:writeTextFile { theFile theContent {theEol lf} } {
133   if {[file exists "${theFile}"]} {
134     set aFileOld [open "${theFile}" rb]
135     fconfigure $aFileOld -translation crlf
136     set aLineListOld [split [read $aFileOld] "\n"]
137     close $aFileOld
138
139     # append empty line for proper comparison (which will be implicitly added by last puts below)
140     set aContent $theContent
141     lappend aContent ""
142     if { [osutils:isEqualContent $aLineListOld $aContent] == true } {
143       return false
144     }
145
146     file delete -force "${theFile}"
147   }
148
149   set anOutFile [open "$theFile" "w"]
150   fconfigure $anOutFile -translation $theEol
151   foreach aLine ${theContent} {
152     puts $anOutFile "${aLine}"
153   }
154   close $anOutFile
155   return true
156 }
157
158 # Function re-generating header files for specified text resource
159 proc genResources { theResource } {
160   global path
161
162   set aResFileList {}
163   set aResourceAbsPath [file normalize "${path}/src/${theResource}"]
164   set aResourceDirectory ""
165   set isResDirectory false
166
167   if {[file isdirectory "${aResourceAbsPath}"]} {
168     if {[file exists "${aResourceAbsPath}/FILES"]} {
169       set aFilesFile [open "${aResourceAbsPath}/FILES" rb]
170       set aResFileList [split [read $aFilesFile] "\n"]
171       close $aFilesFile
172     }
173     set aResFileList [lsearch -inline -all -not -exact $aResFileList ""]
174     set aResourceDirectory "${theResource}"
175     set isResDirectory true
176   } else {
177     set aResourceName [file tail "${theResource}"]
178     lappend aResFileList "res:::${aResourceName}"
179     set aResourceDirectory [file dirname "${theResource}"]
180   }
181
182   foreach aResFileIter ${aResFileList} {
183     if {![regexp {^[^:]+:::(.+)} "${aResFileIter}" dump aResFileIter]} {
184           continue
185         }
186
187     set aResFileName [file tail "${aResFileIter}"]
188     regsub -all {\.} "${aResFileName}" {_} aResFileName
189     set aHeaderFileName "${aResourceDirectory}_${aResFileName}.pxx"
190     if { $isResDirectory == true && [lsearch $aResFileList $aHeaderFileName] == -1 } {
191       continue
192     }
193
194     # generate
195     set aContent {}
196     lappend aContent "// This file has been automatically generated from resource file src/${aResourceDirectory}/${aResFileIter}"
197         lappend aContent ""
198
199     # generate necessary structures
200     set aLineList {}
201     if {[file exists "${path}/src/${aResourceDirectory}/${aResFileIter}"]} {
202       set anInputFile [open "${path}/src/${aResourceDirectory}/${aResFileIter}" rb]
203       fconfigure $anInputFile -translation crlf
204       set aLineList [split [read $anInputFile] "\n"]
205       close $anInputFile
206     }
207
208     # drop empty trailing line
209     set anEndOfFile ""
210     if { [lindex $aLineList end] == "" } {
211       set aLineList [lreplace $aLineList end end]
212       set anEndOfFile "\\n"
213     }
214
215     lappend aContent "static const char ${aResourceDirectory}_${aResFileName}\[\] ="
216     set aNbLines  [llength $aLineList]
217     set aLastLine [expr $aNbLines - 1]
218     for {set aLineIter 0} {$aLineIter < $aNbLines} {incr aLineIter} {
219       set aLine [lindex $aLineList $aLineIter]
220       regsub -all {\"} "${aLine}" {\\"} aLine
221       if { $aLineIter == $aLastLine } {
222         lappend aContent "  \"${aLine}${anEndOfFile}\";"
223       } else {
224         lappend aContent "  \"${aLine}\\n\""
225       }
226     }
227
228     # Save generated content to header file
229     set aHeaderFilePath "${path}/src/${aResourceDirectory}/${aHeaderFileName}"
230     if { [osutils:writeTextFile $aHeaderFilePath $aContent] == true } {
231       puts "Generating header file from resource file: ${path}/src/${aResourceDirectory}/${aResFileIter}"
232     } else {
233           #puts "Header file from resource ${path}/src/${aResourceDirectory}/${aResFileIter} is up-to-date"
234     }
235   }
236 }
237
238 # Function re-generating header files for all text resources
239 proc genAllResources {} {
240   global path
241   set aCasRoot [file normalize $path]
242   if {![file exists "$aCasRoot/adm/RESOURCES"]} {
243     puts "OCCT directory is not defined correctly: $aCasRoot"
244     return
245   }
246
247   set aFileResources [open "$aCasRoot/adm/RESOURCES" rb]
248   set anAdmResources [split [read $aFileResources] "\r\n"]
249   close $aFileResources
250   set anAdmResources [lsearch -inline -all -not -exact $anAdmResources ""]
251
252   foreach line $anAdmResources {
253     genResources "${line}"
254   }
255 }
256
257 # Wrapper-function to generate VS project files
258 proc genproj {theFormat args} {
259   set aSupportedFormats { "vc7" "vc8" "vc9" "vc10" "vc11" "vc12" "vc14" "vc141" "vc142" "cbp" "xcd" "pro"}
260   set aSupportedPlatforms { "wnt" "uwp" "lin" "mac" "ios" "qnx" }
261   set isHelpRequire false
262
263   # check format argument
264   if { $theFormat == "-h" || $theFormat == "-help" || $theFormat == "--help" } {
265     set isHelpRequire true
266   } elseif { [lsearch -exact $aSupportedFormats $theFormat] < 0 } {
267     puts "Error: genproj: unrecognized project format \"$theFormat\""
268     set isHelpRequire true
269   }
270
271   # choice of compiler for Code::Blocks, currently hard-coded
272   set aCmpl "gcc"
273
274   # Determine default platform: wnt for vc*, mac for xcd, current for cbp
275   if { [regexp "^vc" $theFormat] } {
276     set aPlatform "wnt"
277   } elseif { $theFormat == "xcd" || $::tcl_platform(os) == "Darwin" } {
278     set aPlatform "mac"
279   } elseif { $::tcl_platform(platform) == "windows" } {
280     set aPlatform "wnt"
281   } elseif { $::tcl_platform(platform) == "unix" } {
282     set aPlatform "lin"
283   }
284
285   # Check optional arguments
286   set aLibType "dynamic"
287   foreach arg $args {
288     if { $arg == "-h" || $arg == "-help" || $arg == "--help" } {
289       set isHelpRequire true
290     } elseif { [lsearch -exact $aSupportedPlatforms $arg] >= 0 } {
291       set aPlatform $arg
292     } elseif { $arg == "-static" } {
293       set aLibType "static"
294       puts "Static build has been selected"
295     } elseif { $arg == "-dynamic" } {
296       set aLibType "dynamic"
297       puts "Dynamic build has been selected"
298     } else {
299       puts "Error: genproj: unrecognized option \"$arg\""
300       set isHelpRequire true
301     }
302   }
303
304   if {  $isHelpRequire == true } {
305     puts "usage: genproj Format \[Platform\] \[-static\] \[-h|-help|--help\]
306
307     Format must be one of:
308       vc8      -  Visual Studio 2005
309       vc9      -  Visual Studio 2008
310       vc10     -  Visual Studio 2010
311       vc11     -  Visual Studio 2012
312       vc12     -  Visual Studio 2013
313       vc14     -  Visual Studio 2015
314       vc141    -  Visual Studio 2017
315       vc142    -  Visual Studio 2019
316       cbp      -  CodeBlocks
317       xcd      -  XCode
318       pro      -  Qt Creator
319
320     Platform (optional):
321       wnt   -  Windows Desktop
322       uwp   -  Universal Windows Platform
323       lin   -  Linux
324       mac   -  OS X
325       ios   -  iOS
326       qnx   -  QNX
327
328     Option -static can be used with XCode to build static libraries
329     "
330     return
331   }
332
333   if { ! [info exists aPlatform] } {
334     puts "Error: genproj: Cannon identify default platform, please specify!"
335     return
336   }
337
338   puts "Preparing to generate $theFormat projects for $aPlatform platform..."
339
340   # base path to where to generate projects, hardcoded from current dir
341   set anAdmPath [file normalize "${::path}/adm"]
342
343   OS:MKPRC "$anAdmPath" "$theFormat" "$aLibType" "$aPlatform" "$aCmpl"
344
345   genprojbat "$theFormat" "$aPlatform"
346   genAllResources
347 }
348
349 # copy file providing warning if the target file exists and has 
350 # different date or size; if it is newer than source, save it as .bak
351 proc copy_with_warning {from to} {
352   if { [file exists "$to"] &&
353       ([file size   "$to"] != [file size  "$from"] ||
354        [file mtime  "$to"] != [file mtime "$from"]) } {
355     puts "Warning: file $to is updated (copied from $from)!"
356     if { [file mtime $to] > [file mtime $from] } {
357       puts "Info: old content of file $to is saved in ${to}.bak"
358       file copy -force -- "$to" "${to}.bak"
359     }
360   }
361
362   file copy -force -- "$from" "$to"
363 }
364
365 proc genprojbat {theFormat thePlatform} {
366   set aTargetPlatformExt sh
367   if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
368     set aTargetPlatformExt bat
369   }
370
371   if {"$theFormat" != "cmake"} {
372     # copy env.bat/sh only if not yet present
373     if { ! [file exists "$::path/env.${aTargetPlatformExt}"] } {
374       set anEnvTmplFile [open "$::THE_CASROOT/adm/templates/env.${aTargetPlatformExt}" "r"]
375       set anEnvTmpl [read $anEnvTmplFile]
376       close $anEnvTmplFile
377
378       set aCasRoot ""
379       if { [file normalize "$::path"] != [file normalize "$::THE_CASROOT"] } {
380         set aCasRoot [relativePath "$::path" "$::THE_CASROOT"]
381       }
382
383       regsub -all -- {__CASROOT__}   $anEnvTmpl "$aCasRoot" anEnvTmpl
384
385       set anEnvFile [open "$::path/env.${aTargetPlatformExt}" "w"]
386       puts $anEnvFile $anEnvTmpl
387       close $anEnvFile
388     }
389
390     copy_with_warning "$::THE_CASROOT/adm/templates/draw.${aTargetPlatformExt}" "$::path/draw.${aTargetPlatformExt}"
391   }
392
393   if { [regexp {^vc} $theFormat] } {
394     copy_with_warning "$::THE_CASROOT/adm/templates/msvc.bat" "$::path/msvc.bat"
395   } else {
396     switch -exact -- "$theFormat" {
397       "cbp"   {
398         file copy -force -- "$::THE_CASROOT/adm/templates/codeblocks.sh"  "$::path/codeblocks.sh"
399         file copy -force -- "$::THE_CASROOT/adm/templates/codeblocks.bat" "$::path/codeblocks.bat"
400
401         # Code::Blocks 16.01 does not create directory for import libs, help him
402         set aPlatformAndCompiler "${thePlatform}/gcc"
403         if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } {
404           set aPlatformAndCompiler "${thePlatform}/clang"
405         }
406         file mkdir "$::path/${aPlatformAndCompiler}/lib"
407         file mkdir "$::path/${aPlatformAndCompiler}/libd"
408       }
409       "xcd"   { file copy -force -- "$::THE_CASROOT/adm/templates/xcode.sh"      "$::path/xcode.sh" }
410     }
411   }
412 }
413
414 ###### MSVC #############################################################33
415 proc removeAllOccurrencesOf { theObject theList } {
416   set aSortIndices [lsort -decreasing [lsearch -all -nocase $theList $theObject]]
417   foreach anIndex $aSortIndices {
418     set theList [lreplace $theList $anIndex $anIndex]
419   }
420   return $theList
421 }
422
423 set aTKNullKey "TKNull"
424 set THE_GUIDS_LIST($aTKNullKey) "{00000000-0000-0000-0000-000000000000}"
425
426 # Entry function to generate project files
427 # @param theOutDir   Root directory for project files
428 # @param theFormat   Project format name (vc.. for Visual Studio projects, cbp for Code::Blocks, xcd for XCode)
429 # @param theLibType  Library type - dynamic or static
430 # @param thePlatform Optional target platform for cross-compiling, e.g. ios for iOS
431 # @param theCmpl     Compiler option (msvc or gcc)
432 proc OS:MKPRC { theOutDir theFormat theLibType thePlatform theCmpl } {
433   global path
434   set anOutRoot $theOutDir
435   if { $anOutRoot == "" } {
436     error "Error : \"theOutDir\" is not initialized"
437   }
438
439   # Create output directory
440   set aWokStation "$thePlatform"
441   if { [regexp {^vc} $theFormat] } {
442     set aWokStation "msvc"
443   }
444   set aSuffix ""
445   set isUWP 0
446   if { $thePlatform == "uwp" } {
447     set aSuffix "-uwp"
448     set isUWP 1
449   }
450   set anOutDir "${anOutRoot}/${aWokStation}/${theFormat}${aSuffix}"
451
452   # read map of already generated GUIDs
453   set aGuidsFilePath [file join $anOutDir "wok_${theFormat}_guids.txt"]
454   if [file exists "$aGuidsFilePath"] {
455     set aFileIn [open "$aGuidsFilePath" r]
456     set aFileDataRaw [read $aFileIn]
457     close $aFileIn
458     set aFileData [split $aFileDataRaw "\n"]
459     foreach aLine $aFileData {
460       set aLineSplt [split $aLine "="]
461       if { [llength $aLineSplt] == 2 } {
462         set ::THE_GUIDS_LIST([lindex $aLineSplt 0]) [lindex $aLineSplt 1]
463       }
464     }
465   }
466
467   # make list of modules and platforms
468   set aModules [OS:init]
469   if { "$thePlatform" == "ios" } {
470     set goaway [list Draw]
471     set aModules [osutils:juststation $goaway $aModules]
472   }
473
474   # Draw module is turned off due to it is not supported on UWP
475   if { $isUWP } {
476     set aDrawIndex [lsearch -exact ${aModules} "Draw"]
477     if { ${aDrawIndex} != -1 } {
478       set aModules [lreplace ${aModules} ${aDrawIndex} ${aDrawIndex}]
479     }
480   }
481
482   # create the out dir if it does not exist
483   if (![file isdirectory $path/inc]) {
484     puts "$path/inc folder does not exists and will be created"
485     wokUtils:FILES:mkdir $path/inc
486   }
487
488   # collect all required header files
489   puts "Collecting required header files into $path/inc ..."
490   osutils:collectinc $aModules $path/inc
491
492   if { "$theFormat" == "pro" } {
493     return
494   }
495
496   # generate one solution for all projects if complete OS or VAS is processed
497   set anAllSolution "OCCT"
498
499   wokUtils:FILES:mkdir $anOutDir
500   if { ![file exists $anOutDir] } {
501     puts stderr "Error: Could not create output directory \"$anOutDir\""
502     return
503   }
504
505   # Generating project files for the selected format
506   switch -exact -- "$theFormat" {
507     "vc7"   -
508     "vc8"   -
509     "vc9"   -
510     "vc10"  -
511     "vc11"  -
512     "vc12"  -
513     "vc14"  -
514     "vc141" -
515     "vc142"    { OS:MKVC  $anOutDir $aModules $anAllSolution $theFormat $isUWP}
516     "cbp"      { OS:MKCBP $anOutDir $aModules $anAllSolution $thePlatform $theCmpl }
517     "xcd"      {
518       set ::THE_GUIDS_LIST($::aTKNullKey) "000000000000000000000000"
519       OS:MKXCD $anOutDir $aModules $anAllSolution $theLibType $thePlatform
520     }
521   }
522
523   # Store generated GUIDs map
524   set anOutFile [open "$aGuidsFilePath" "w"]
525   fconfigure $anOutFile -translation lf
526   foreach aKey [array names ::THE_GUIDS_LIST] {
527     set aValue $::THE_GUIDS_LIST($aKey)
528     puts $anOutFile "${aKey}=${aValue}"
529   }
530   close $anOutFile
531 }
532
533 # Function to generate Visual Studio solution and project files
534 proc OS:MKVC { theOutDir theModules theAllSolution theVcVer isUWP } {
535
536   puts stderr "Generating VS project files for $theVcVer"
537
538   # generate projects for toolkits and separate solution for each module
539   foreach aModule $theModules {
540     OS:vcsolution $theVcVer $aModule $aModule $theOutDir ::THE_GUIDS_LIST
541     OS:vcproj     $theVcVer $isUWP   $aModule $theOutDir ::THE_GUIDS_LIST
542   }
543
544   # generate single solution "OCCT" containing projects from all modules
545   if { "$theAllSolution" != "" } {
546     OS:vcsolution $theVcVer $theAllSolution $theModules $theOutDir ::THE_GUIDS_LIST
547   }
548
549   puts "The Visual Studio solution and project files are stored in the $theOutDir directory"
550 }
551
552 proc OS:init {{os {}}} {
553   set askplat $os
554   set aModules {}
555   if { "$os" == "" } {
556     set os $::tcl_platform(os)
557   }
558
559   if [file exists "$::path/src/VAS/Products.tcl"] {
560     source "$::path/src/VAS/Products.tcl"
561     foreach aModuleIter [VAS:Products] {
562       set aFileTcl "$::path/src/VAS/${aModuleIter}.tcl"
563       if [file exists $aFileTcl] {
564         source $aFileTcl
565         lappend aModules $aModuleIter
566       } else {
567         puts stderr "Definition file for module $aModuleIter is not found in unit VAS"
568       }
569     }
570     return $aModules
571   }
572
573   # Load list of OCCT modules and their definitions
574   source "$::path/src/OS/Modules.tcl"
575   foreach aModuleIter [OS:Modules] {
576     set aFileTcl "$::path/src/OS/${aModuleIter}.tcl"
577     if [file exists $aFileTcl] {
578       source $aFileTcl
579       lappend aModules $aModuleIter
580     } else {
581       puts stderr "Definition file for module $aModuleIter is not found in unit OS"
582     }
583   }
584
585   return $aModules
586 }
587
588 # topological sort. returns a list {  {a h} {b g} {c f} {c h} {d i}  } => { d a b c i g f h }
589 proc wokUtils:EASY:tsort { listofpairs } {
590     foreach x $listofpairs {
591         set e1 [lindex $x 0]
592         set e2 [lindex $x 1]
593         if ![info exists pcnt($e1)] {
594             set pcnt($e1) 0
595         }
596         if ![ info exists pcnt($e2)] {
597             set pcnt($e2) 1
598         } else {
599             incr pcnt($e2)
600         }
601         if ![info exists scnt($e1)] {
602             set scnt($e1) 1
603         } else {
604             incr scnt($e1)
605         }
606         set l {}
607         if [info exists slist($e1)] {
608             set l $slist($e1)
609         }
610         lappend l $e2
611         set slist($e1) $l
612     }
613     set nodecnt 0
614     set back 0
615     foreach node [array names pcnt] {
616         incr nodecnt
617         if { $pcnt($node) == 0 } {
618             incr back
619             set q($back) $node
620         }
621         if ![info exists scnt($node)] {
622             set scnt($node) 0
623         }
624     }
625     set res {}
626     for {set front 1} { $front <= $back } { incr front } {
627         lappend res [set node $q($front)]
628         for {set i 1} {$i <= $scnt($node) } { incr i } {
629             set ll $slist($node)
630             set j [expr {$i - 1}]
631             set u [expr { $pcnt([lindex $ll $j]) - 1 }]
632             if { [set pcnt([lindex $ll $j]) $u] == 0 } {
633                 incr back
634                 set q($back) [lindex $ll $j]
635             }
636         }
637     }
638     if { $back != $nodecnt } {
639         puts stderr "input contains a cycle"
640         return {}
641     } else {
642         return $res
643     }
644 }
645
646 proc wokUtils:LIST:Purge { l } {
647     set r {}
648      foreach e $l {
649          if ![info exist tab($e)] {
650              lappend r $e
651              set tab($e) {}
652          } 
653      }
654      return $r
655 }
656
657 # Read file pointed to by path
658 # 1. sort = 1 tri 
659 # 2. trim = 1 plusieurs blancs => 1 seul blanc
660 # 3. purge= not yet implemented.
661 # 4. emptl= dont process blank lines
662 proc wokUtils:FILES:FileToList { path {sort 0} {trim 0} {purge 0} {emptl 1} } {
663     if ![ catch { set id [ open $path r ] } ] {
664         set l  {}
665         while {[gets $id line] >= 0 } {
666             if { $trim } {
667                 regsub -all {[ ]+} $line " " line
668             }
669             if { $emptl } {
670                 if { [string length ${line}] != 0 } {
671                     lappend l $line
672                 }
673             } else {
674                 lappend l $line
675             }
676         }
677         close $id
678         if { $sort } {
679             return [lsort $l]
680         } else {
681             return $l
682         }
683     } else {
684         return {}
685     }
686 }
687
688 # retorn the list of executables in module.
689 proc OS:executable { module } {
690     set lret {}
691     foreach XXX  [${module}:ressources] {
692         if { "[lindex $XXX 1]" == "x" } {
693             lappend lret [lindex $XXX 2]
694         }
695     }
696     return $lret
697 }
698
699 # Topological sort of toolkits in tklm
700 proc osutils:tk:sort { tklm } {
701   set tkby2 {}
702   foreach tkloc $tklm {
703     set lprg [wokUtils:LIST:Purge [osutils:tk:close $tkloc]]
704     foreach tkx  $lprg {
705       if { [lsearch $tklm $tkx] != -1 } {
706         lappend tkby2 [list $tkx $tkloc]
707       } else {
708         lappend tkby2 [list $tkloc {}]
709       }
710     }
711   }
712   set lret {}
713   foreach e [wokUtils:EASY:tsort $tkby2] {
714     if { $e != {} } {
715       lappend lret $e
716     }
717   }
718   return $lret
719 }
720
721 #  close dependencies of ltk. (full wok pathes of toolkits)
722 # The CURRENT WOK LOCATION MUST contains ALL TOOLKITS required.
723 # (locate not performed.)
724 proc osutils:tk:close { ltk } {
725   set result {}
726   set recurse {}
727   foreach dir $ltk {
728     set ids [LibToLink $dir]
729 #    puts "osutils:tk:close($ltk) ids='$ids'"
730     set eated [osutils:tk:eatpk $ids]
731     set result [concat $result $eated]
732     set ids [LibToLink $dir]
733     set result [concat $result $ids]
734
735     foreach file $eated {
736       set kds [osutils:findSrcSubPath "$file/EXTERNLIB"]
737       if { [osutils:tk:eatpk $kds] !=  {} } {
738         lappend recurse $file
739       }
740     }
741   }
742   if { $recurse != {} } {
743     set result [concat $result [osutils:tk:close $recurse]]
744   }
745   return $result
746 }
747
748 proc osutils:tk:eatpk { EXTERNLIB  } {
749   set l [wokUtils:FILES:FileToList $EXTERNLIB]
750   set lret  {}
751   foreach str $l {
752     if ![regexp -- {(CSF_[^ ]*)} $str csf] {
753       lappend lret $str
754     }
755   }
756   return $lret
757 }
758 # Define libraries to link using only EXTERNLIB file
759
760 proc LibToLink {theTKit} {
761   regexp {^.*:([^:]+)$} $theTKit dummy theTKit
762   set type [_get_type $theTKit]
763   if {$type != "t" && $type != "x"} {
764     return
765   }
766   set aToolkits {}
767   set anExtLibList [osutils:tk:eatpk [osutils:findSrcSubPath "$theTKit/EXTERNLIB"]]
768   foreach anExtLib $anExtLibList {
769     set aFullPath [LocateRecur $anExtLib]
770     if { "$aFullPath" != "" && [_get_type $anExtLib] == "t" } {
771       lappend aToolkits $anExtLib
772     }
773   }
774   return $aToolkits
775 }
776 # Search unit recursively
777
778 proc LocateRecur {theName} {
779   set theNamePath [osutils:findSrcSubPath "$theName"]
780   if {[file isdirectory $theNamePath]} {
781     return $theNamePath
782   }
783   return ""
784 }
785
786 proc OS:genGUID { {theFormat "vc"} } {
787   if { "$theFormat" == "vc" } {
788     set p1 "[format %07X [expr { int(rand() * 268435456) }]][format %X [expr { int(rand() * 16) }]]"
789     set p2 "[format %04X [expr { int(rand() * 6536) }]]"
790     set p3 "[format %04X [expr { int(rand() * 6536) }]]"
791     set p4 "[format %04X [expr { int(rand() * 6536) }]]"
792     set p5 "[format %06X [expr { int(rand() * 16777216) }]][format %06X [expr { int(rand() * 16777216) }]]"
793     return "{$p1-$p2-$p3-$p4-$p5}"
794   } else {
795     set p1 "[format %04X [expr { int(rand() * 6536) }]]"
796     set p2 "[format %04X [expr { int(rand() * 6536) }]]"
797     set p3 "[format %04X [expr { int(rand() * 6536) }]]"
798     set p4 "[format %04X [expr { int(rand() * 6536) }]]"
799     set p5 "[format %04X [expr { int(rand() * 6536) }]]"
800     set p6 "[format %04X [expr { int(rand() * 6536) }]]"
801     return "$p1$p2$p3$p4$p5$p6"
802   }
803 }
804
805 # collect all include file that required for theModules in theOutDir
806 proc osutils:collectinc {theModules theIncPath} {
807   global path
808   set aCasRoot [file normalize $path]
809   set anIncPath [file normalize $theIncPath]
810
811   if {![file isdirectory $aCasRoot]} {
812     puts "OCCT directory is not defined correctly: $aCasRoot"
813     return
814   }
815
816   set anUsedToolKits {}
817   foreach aModule $theModules {
818     foreach aToolKit [${aModule}:toolkits] {
819       lappend anUsedToolKits $aToolKit
820
821       foreach aDependency [LibToLink $aToolKit] {
822         lappend anUsedToolKits $aDependency
823       }
824     }
825     foreach anExecutable [OS:executable ${aModule}] {
826       lappend anUsedToolKits $anExecutable
827
828       foreach aDependency [LibToLink $anExecutable] {
829         lappend anUsedToolKits $aDependency
830       }
831     }
832   }
833   set anUsedToolKits [lsort -unique $anUsedToolKits]
834
835   set anUnits {}
836   foreach anUsedToolKit $anUsedToolKits {
837     set anUnits [concat $anUnits [osutils:tk:units $anUsedToolKit]]
838   }
839   set anUnits [lsort -unique $anUnits]
840
841   # define copying style
842   set aCopyType "copy"
843   if { [info exists ::env(SHORTCUT_HEADERS)] } {
844     if { [string equal -nocase $::env(SHORTCUT_HEADERS) "hard"]
845       || [string equal -nocase $::env(SHORTCUT_HEADERS) "hardlink"] } {
846       set aCopyType "hardlink"
847     } elseif { [string equal -nocase $::env(SHORTCUT_HEADERS) "true"]
848             || [string equal -nocase $::env(SHORTCUT_HEADERS) "shortcut"] } {
849       set aCopyType "shortcut"
850     }
851   }
852
853   set allHeaderFiles {}
854   if { $aCopyType == "shortcut" } {
855     # template preparation
856     if { ![file exists $::THE_CASROOT/adm/templates/header.in] } {
857       puts "template file does not exist: $::THE_CASROOT/adm/templates/header.in"
858       return
859     }
860     set aHeaderTmpl [wokUtils:FILES:FileToString $::THE_CASROOT/adm/templates/header.in]
861
862     # relative anIncPath in connection with aCasRoot/src
863     set aFromBuildIncToSrcPath [relativePath "$anIncPath" "$aCasRoot/src"]
864
865     # create and copy short-cut header files
866     foreach anUnit $anUnits {
867       osutils:checksrcfiles ${anUnit}
868
869       set aHFiles [_get_used_files ${anUnit} true false]
870       foreach aHeaderFile ${aHFiles} {
871         set aHeaderFileName [lindex ${aHeaderFile} 1]
872         lappend allHeaderFiles "${aHeaderFileName}"
873
874         regsub -all -- {@OCCT_HEADER_FILE_CONTENT@} $aHeaderTmpl "#include \"$aFromBuildIncToSrcPath/$anUnit/$aHeaderFileName\"" aShortCutHeaderFileContent
875
876         if {[file exists "$theIncPath/$aHeaderFileName"] && [file readable "$theIncPath/$aHeaderFileName"]} {
877           set fp [open "$theIncPath/$aHeaderFileName" r]
878           set aHeaderContent [read $fp]
879           close $fp
880
881           # minus eof
882           set aHeaderLenght  [expr [string length $aHeaderContent] - 1]
883
884           if {$aHeaderLenght == [string length $aShortCutHeaderFileContent]} {
885             # remove eof from string
886             set aHeaderContent [string range $aHeaderContent 0 [expr $aHeaderLenght - 1]]
887
888             if {[string compare $aShortCutHeaderFileContent $aHeaderContent] == 0} {
889               continue
890             }
891           }
892           file delete -force "$theIncPath/$aHeaderFileName"
893         }
894
895         set aShortCutHeaderFile [open "$theIncPath/$aHeaderFileName" "w"]
896         fconfigure $aShortCutHeaderFile -translation lf
897         puts $aShortCutHeaderFile $aShortCutHeaderFileContent
898         close $aShortCutHeaderFile
899       }
900     }
901   } else {
902     set nbcopied 0
903     foreach anUnit $anUnits {
904       osutils:checksrcfiles ${anUnit}
905
906       set aHFiles [_get_used_files ${anUnit} true false]
907       foreach aHeaderFile ${aHFiles} {
908         set aHeaderFileName [lindex ${aHeaderFile} 1]
909         lappend allHeaderFiles "${aHeaderFileName}"
910
911         # copy file only if target does not exist or is older than original
912         set torig [file mtime $aCasRoot/src/$anUnit/$aHeaderFileName]
913         set tcopy 0
914         if { [file isfile $anIncPath/$aHeaderFileName] } {
915           set tcopy [file mtime $anIncPath/$aHeaderFileName]
916         }
917         if { $tcopy < $torig } {
918           incr nbcopied
919           if { $aCopyType == "hardlink" } {
920             if { $tcopy != 0 } {
921               file delete -force "$theIncPath/$aHeaderFileName"
922             }
923             file link -hard  $anIncPath/$aHeaderFileName $aCasRoot/src/$anUnit/$aHeaderFileName
924           } else {
925             file copy -force $aCasRoot/src/$anUnit/$aHeaderFileName $anIncPath/$aHeaderFileName
926           }
927         } elseif { $tcopy != $torig } {
928           puts "Warning: file $anIncPath/$aHeaderFileName is newer than $aCasRoot/src/$anUnit/$aHeaderFileName, not changed!"
929         }
930       }
931     }
932     puts "Info: $nbcopied files updated"
933   }
934
935   # remove header files not listed in FILES
936   set anIncFiles [glob -tails -nocomplain -dir ${anIncPath} "*"]
937   foreach anIncFile ${anIncFiles} {
938     if { [lsearch -exact ${allHeaderFiles} ${anIncFile}] == -1 } {
939       puts "Warning: file ${anIncPath}/${anIncFile} is not present in the sources and will be removed from ${theIncPath}"
940       file delete -force "${theIncPath}/${anIncFile}"
941     }
942   }
943 }
944
945 # Generate header for VS solution file
946 proc osutils:vcsolution:header { vcversion } {
947   if { "$vcversion" == "vc7" } {
948     append var \
949       "Microsoft Visual Studio Solution File, Format Version 8.00\n"
950   } elseif { "$vcversion" == "vc8" } {
951     append var \
952       "Microsoft Visual Studio Solution File, Format Version 9.00\n" \
953       "# Visual Studio 2005\n"
954   } elseif { "$vcversion" == "vc9" } {
955     append var \
956       "Microsoft Visual Studio Solution File, Format Version 10.00\n" \
957       "# Visual Studio 2008\n"
958   } elseif { "$vcversion" == "vc10" } {
959     append var \
960       "Microsoft Visual Studio Solution File, Format Version 11.00\n" \
961       "# Visual Studio 2010\n"
962   } elseif { "$vcversion" == "vc11" } {
963     append var \
964       "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
965       "# Visual Studio 2012\n"
966   } elseif { "$vcversion" == "vc12" } {
967     append var \
968       "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
969       "# Visual Studio 2013\n"
970   } elseif { "$vcversion" == "vc14" || "$vcversion" == "vc141" || "$vcversion" == "vc142" } {
971     append var \
972       "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
973       "# Visual Studio 14\n"
974   } else {
975     puts stderr "Error: Visual Studio version $vcversion is not supported by this function!"
976   }
977   return $var
978 }
979 # Returns extension (without dot) for project files of given version of VC
980
981 proc osutils:vcproj:ext { vcversion } {
982   if { "$vcversion" == "vc7" || "$vcversion" == "vc8" || "$vcversion" == "vc9" } {
983     return "vcproj"
984   } else {
985     return "vcxproj"
986   }
987 }
988 # Generate start of configuration section of VS solution file
989
990 proc osutils:vcsolution:config:begin { vcversion } {
991   if { "$vcversion" == "vc7" } {
992     append var \
993       "Global\n" \
994       "\tGlobalSection(SolutionConfiguration) = preSolution\n" \
995       "\t\tDebug = Debug\n" \
996       "\t\tRelease = Release\n" \
997       "\tEndGlobalSection\n" \
998       "\tGlobalSection(ProjectConfiguration) = postSolution\n"
999   } else {
1000     append var \
1001       "Global\n" \
1002       "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n" \
1003       "\t\tDebug|Win32 = Debug|Win32\n" \
1004       "\t\tRelease|Win32 = Release|Win32\n" \
1005       "\t\tDebug|x64 = Debug|x64\n" \
1006       "\t\tRelease|x64 = Release|x64\n" \
1007       "\tEndGlobalSection\n" \
1008       "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"
1009   }
1010   return $var
1011 }
1012 # Generate part of configuration section of VS solution file describing one project
1013
1014 proc osutils:vcsolution:config:project { vcversion guid } {
1015   if { "$vcversion" == "vc7" } {
1016     append var \
1017       "\t\t$guid.Debug.ActiveCfg = Debug|Win32\n" \
1018       "\t\t$guid.Debug.Build.0 = Debug|Win32\n" \
1019       "\t\t$guid.Release.ActiveCfg = Release|Win32\n" \
1020       "\t\t$guid.Release.Build.0 = Release|Win32\n"
1021   } else {
1022     append var \
1023       "\t\t$guid.Debug|Win32.ActiveCfg = Debug|Win32\n" \
1024       "\t\t$guid.Debug|Win32.Build.0 = Debug|Win32\n" \
1025       "\t\t$guid.Release|Win32.ActiveCfg = Release|Win32\n" \
1026       "\t\t$guid.Release|Win32.Build.0 = Release|Win32\n" \
1027       "\t\t$guid.Debug|x64.ActiveCfg = Debug|x64\n" \
1028       "\t\t$guid.Debug|x64.Build.0 = Debug|x64\n" \
1029       "\t\t$guid.Release|x64.ActiveCfg = Release|x64\n" \
1030       "\t\t$guid.Release|x64.Build.0 = Release|x64\n"
1031   }
1032   return $var
1033 }
1034 # Generate start of configuration section of VS solution file
1035
1036 proc osutils:vcsolution:config:end { vcversion } {
1037   if { "$vcversion" == "vc7" } {
1038     append var \
1039       "\tEndGlobalSection\n" \
1040       "\tGlobalSection(ExtensibilityGlobals) = postSolution\n" \
1041       "\tEndGlobalSection\n" \
1042       "\tGlobalSection(ExtensibilityAddIns) = postSolution\n" \
1043       "\tEndGlobalSection\n"
1044   } else {
1045     append var \
1046       "\tEndGlobalSection\n" \
1047       "\tGlobalSection(SolutionProperties) = preSolution\n" \
1048       "\t\tHideSolutionNode = FALSE\n" \
1049       "\tEndGlobalSection\n"
1050   }
1051   return $var
1052 }
1053 # generate Visual Studio solution file
1054 # if module is empty, generates one solution for all known modules
1055
1056 proc OS:vcsolution { theVcVer theSolName theModules theOutDir theGuidsMap } {
1057   global path
1058   upvar $theGuidsMap aGuidsMap
1059
1060   # collect list of projects to be created
1061   set aProjects {}
1062   set aDependencies {}
1063   foreach aModule $theModules {
1064     # toolkits
1065     foreach aToolKit [osutils:tk:sort [${aModule}:toolkits]] {
1066       lappend aProjects $aToolKit
1067       lappend aProjectsInModule($aModule) $aToolKit
1068       lappend aDependencies [LibToLink $aToolKit]
1069     }
1070     # executables, assume one project per cxx file...
1071     foreach aUnit [OS:executable ${aModule}] {
1072       set aUnitLoc $aUnit
1073       set src_files [_get_used_files $aUnit false]
1074       set aSrcFiles {}
1075       foreach s $src_files {
1076         regexp {source ([^\s]+)} $s dummy name
1077         lappend aSrcFiles $name
1078       }
1079       foreach aSrcFile $aSrcFiles {
1080         set aFileExtension [file extension $aSrcFile]
1081         if { $aFileExtension == ".cxx" } {
1082           set aPrjName [file rootname $aSrcFile]
1083           lappend aProjects $aPrjName
1084           lappend aProjectsInModule($aModule) $aPrjName
1085           if {[file isdirectory $path/src/$aUnitLoc]} {
1086             lappend aDependencies [LibToLinkX $aUnitLoc [file rootname $aSrcFile]]
1087           } else {
1088             lappend aDependencies {}
1089           }
1090         }
1091       }
1092     }
1093   }
1094
1095 # generate GUIDs for projects (unless already known)
1096   foreach aProject $aProjects {
1097     if { ! [info exists aGuidsMap($aProject)] } {
1098       set aGuidsMap($aProject) [OS:genGUID]
1099     }
1100   }
1101
1102   # generate solution file
1103 #  puts "Generating Visual Studio ($theVcVer) solution file for $theSolName ($aProjects)"
1104   append aFileBuff [osutils:vcsolution:header $theVcVer]
1105
1106   # GUID identifying group projects in Visual Studio
1107   set VC_GROUP_GUID "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"
1108
1109   # generate group projects -- one per module
1110   if { "$theVcVer" != "vc7" && [llength "$theModules"] > 1 } {
1111     foreach aModule $theModules {
1112       if { ! [info exists aGuidsMap(_$aModule)] } {
1113         set aGuidsMap(_$aModule) [OS:genGUID]
1114       }
1115       set aGuid $aGuidsMap(_$aModule)
1116       append aFileBuff "Project(\"${VC_GROUP_GUID}\") = \"$aModule\", \"$aModule\", \"$aGuid\"\nEndProject\n"
1117     }
1118   }
1119
1120   # extension of project files
1121   set aProjExt [osutils:vcproj:ext $theVcVer]
1122
1123   # GUID identifying C++ projects in Visual Studio
1124   set VC_CPP_GUID "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"
1125
1126   # generate normal projects
1127   set aProjsNb [llength $aProjects]
1128   for {set aProjId 0} {$aProjId < $aProjsNb} {incr aProjId} {
1129     set aProj [lindex $aProjects $aProjId]
1130     set aGuid $aGuidsMap($aProj)
1131     append aFileBuff "Project(\"${VC_CPP_GUID}\") = \"$aProj\", \"$aProj.${aProjExt}\", \"$aGuid\"\n"
1132     # write projects dependencies information (vc7 to vc9)
1133     set aDepGuids ""
1134     foreach aDepLib [lindex $aDependencies $aProjId] {
1135       if { $aDepLib != $aProj && [lsearch $aProjects $aDepLib] != "-1" } {
1136         set depGUID $aGuidsMap($aDepLib)
1137         append aDepGuids "\t\t$depGUID = $depGUID\n"
1138       }
1139     }
1140     if { "$aDepGuids" != "" } {
1141       append aFileBuff "\tProjectSection(ProjectDependencies) = postProject\n"
1142       append aFileBuff "$aDepGuids"
1143       append aFileBuff "\tEndProjectSection\n"
1144     }
1145     append aFileBuff "EndProject\n"
1146   }
1147
1148   # generate configuration section
1149   append aFileBuff [osutils:vcsolution:config:begin $theVcVer]
1150   foreach aProj $aProjects {
1151     append aFileBuff [osutils:vcsolution:config:project $theVcVer $aGuidsMap($aProj)]
1152   }
1153   append aFileBuff [osutils:vcsolution:config:end $theVcVer]
1154
1155   # write information of grouping of projects by module
1156   if { "$theVcVer" != "vc7" && [llength "$theModules"] > 1 } {
1157     append aFileBuff "  GlobalSection(NestedProjects) = preSolution\n"
1158     foreach aModule $theModules {
1159       if { ! [info exists aProjectsInModule($aModule)] } { continue }
1160       foreach aProject $aProjectsInModule($aModule) {
1161         append aFileBuff "              $aGuidsMap($aProject) = $aGuidsMap(_$aModule)\n"
1162       }
1163     }
1164     append aFileBuff "  EndGlobalSection\n"
1165   }
1166
1167   # final word (footer)
1168   append aFileBuff "EndGlobal"
1169
1170   # write solution
1171   set aFile [open [set fdsw [file join $theOutDir ${theSolName}.sln]] w]
1172   fconfigure $aFile -translation crlf
1173   puts $aFile $aFileBuff
1174   close $aFile
1175   return [file join $theOutDir ${theSolName}.sln]
1176 }
1177 # Generate Visual Studio projects for specified version
1178
1179 proc OS:vcproj { theVcVer isUWP theModules theOutDir theGuidsMap } {
1180   upvar $theGuidsMap aGuidsMap
1181
1182   set aProjectFiles {}
1183
1184   foreach aModule $theModules {
1185     foreach aToolKit [${aModule}:toolkits] {
1186       lappend aProjectFiles [osutils:vcproj  $theVcVer $isUWP $theOutDir $aToolKit     aGuidsMap]
1187     }
1188     foreach anExecutable [OS:executable ${aModule}] {
1189       lappend aProjectFiles [osutils:vcprojx $theVcVer $isUWP $theOutDir $anExecutable aGuidsMap]
1190     }
1191   }
1192   return $aProjectFiles
1193 }
1194 # generate template name and load it for given version of Visual Studio and platform
1195
1196 proc osutils:vcproj:readtemplate {theVcVer isUWP isExec} {
1197   set anExt $theVcVer
1198   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1199     set anExt vc10
1200   }
1201
1202   # determine versions of runtime and toolset
1203   set aVCRTVer $theVcVer 
1204   set aToolset "v[string range $theVcVer 2 3]0"
1205   if { $theVcVer == "vc141" } {
1206     set aVCRTVer "vc14"
1207     set aToolset "v141"
1208   } elseif { $theVcVer == "vc142" } {
1209     set aVCRTVer "vc14"
1210     set aToolset "v142"
1211   }
1212
1213   set what "$theVcVer"
1214   set aCmpl32 ""
1215   set aCmpl64 ""
1216   set aCharSet "Unicode"
1217   if { $isExec } {
1218     set anExt "${anExt}x"
1219     set what "$what executable"
1220   }
1221   if { "$theVcVer" == "vc10" } {
1222     # SSE2 is enabled by default in vc11+, but not in vc10 for 32-bit target
1223     set aCmpl32 "<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>"
1224   }
1225   set aTmpl [osutils:readtemplate $anExt "MS VC++ project ($what)"]
1226
1227   if { $isUWP } {
1228     set UwpWinRt "<CompileAsWinRT>false</CompileAsWinRT>"
1229     foreach bitness {32 64} {
1230       set indent ""
1231       if {"[set aCmpl${bitness}]" != ""} {
1232         set indent "\n      "
1233       }
1234       set aCmpl${bitness} "[set aCmpl${bitness}]${indent}${UwpWinRt}"
1235     }
1236   }
1237
1238   set format_template "\[\\r\\n\\s\]*"
1239   foreach bitness {32 64} {
1240     set format_templateloc ""
1241     if {"[set aCmpl${bitness}]" == ""} {
1242       set format_templateloc "$format_template"
1243     }
1244     regsub -all -- "${format_templateloc}__VCMPL${bitness}__" $aTmpl "[set aCmpl${bitness}]" aTmpl
1245   }
1246
1247   set aDebugInfo "no"
1248   set aReleaseLnk ""
1249   if { "$::HAVE_RelWithDebInfo" == "true" } {
1250     set aDebugInfo "true"
1251     set aReleaseLnk "\n      <OptimizeReferences>true</OptimizeReferences>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>"
1252   }
1253
1254   regsub -all -- {__VCVER__}     $aTmpl $aVCRTVer aTmpl
1255   regsub -all -- {__VCVEREXT__}  $aTmpl $aToolset aTmpl
1256   regsub -all -- {__VCCHARSET__} $aTmpl $aCharSet aTmpl
1257   regsub -all -- {__VCReleasePDB__} $aTmpl $aDebugInfo aTmpl
1258   regsub -all -- "${format_template}__VCLNKREL__" $aTmpl "${aReleaseLnk}" aTmpl
1259
1260   return $aTmpl
1261 }
1262
1263 proc osutils:readtemplate {ext what} {
1264   set loc "$::THE_CASROOT/adm/templates/template.$ext"
1265   return [wokUtils:FILES:FileToString $loc]
1266 }
1267 # Read a file in a string as is.
1268
1269 proc wokUtils:FILES:FileToString { fin } {
1270     if { [catch { set in [ open $fin r ] } errin] == 0 } {
1271         set strin [read $in [file size $fin]]
1272         close $in
1273         return $strin
1274     } else {
1275         return {}
1276     }
1277 }
1278
1279 # List extensions of compilable files in OCCT
1280 proc osutils:compilable {thePlatform} {
1281   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } { return [list .c .cxx .cpp .mm] }
1282   return [list .c .cxx .cpp]
1283 }
1284
1285 # List extensions of header file in OCCT
1286 proc osutils:fileExtensionsHeaders {thePlatform} {
1287   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } { return [list .h .hxx .hpp .lxx .pxx .gxx ] }
1288   return [list .h .hxx .hpp .lxx .pxx .gxx .mm ]
1289 }
1290
1291 proc osutils:commonUsedTK { theToolKit } {
1292   set anUsedToolKits [list]
1293   set aDepToolkits [LibToLink $theToolKit]
1294   foreach tkx $aDepToolkits {
1295     if {[_get_type $tkx] == "t"} {
1296       lappend anUsedToolKits "${tkx}"
1297     }
1298   }
1299   return $anUsedToolKits
1300 }
1301
1302 # Return the list of name *CSF_ in a EXTERNLIB description of a toolkit
1303 proc osutils:tk:csfInExternlib { EXTERNLIB } {
1304   set l [wokUtils:FILES:FileToList $EXTERNLIB]
1305   set lret  {STLPort}
1306   foreach str $l {
1307     if [regexp -- {(CSF_[^ ]*)} $str csf] {
1308       lappend lret $csf
1309     }
1310   }
1311   return $lret
1312 }
1313
1314 # Collect dependencies map depending on target OS (libraries for CSF_ codenames used in EXTERNLIB) .
1315 # @param theOS         - target OS
1316 # @param theCsfLibsMap - libraries  map
1317 # @param theCsfFrmsMap - frameworks map, OS X specific
1318 proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap } {
1319   upvar $theCsfLibsMap aLibsMap
1320   upvar $theCsfFrmsMap aFrmsMap
1321
1322   unset theCsfLibsMap
1323   unset theCsfFrmsMap
1324
1325   set aLibsMap(CSF_FREETYPE)  "freetype"
1326   set aLibsMap(CSF_TclLibs)   "tcl8.6"
1327   set aLibsMap(CSF_TclTkLibs) "tk8.6"
1328   if { "$::HAVE_FREEIMAGE" == "true" } {
1329     if { "$theOS" == "wnt" } {
1330       set aLibsMap(CSF_FreeImagePlus) "FreeImage"
1331     } else {
1332       set aLibsMap(CSF_FreeImagePlus) "freeimage"
1333     }
1334   } elseif { "$theOS" == "wnt" } {
1335     set aLibsMap(CSF_FreeImagePlus) "windowscodecs"
1336   }
1337   if { "$::HAVE_FFMPEG" == "true" } {
1338     set aLibsMap(CSF_FFmpeg) "avcodec avformat swscale avutil"
1339   }
1340   if { "$::HAVE_TBB" == "true" } {
1341     set aLibsMap(CSF_TBB) "tbb tbbmalloc"
1342   }
1343   if { "$::HAVE_VTK" == "true" } {
1344     if { "$theOS" == "wnt" } {
1345       set aLibsMap(CSF_VTK) [osutils:vtkCsf "wnt"]
1346     } else {
1347       set aLibsMap(CSF_VTK) [osutils:vtkCsf "unix"]
1348     }
1349   }
1350   if { "$::HAVE_ZLIB" == "true" } {
1351     set aLibsMap(CSF_ZLIB) "zlib"
1352   }
1353   if { "$::HAVE_LIBLZMA" == "true" } {
1354     set aLibsMap(CSF_LIBLZMA) "liblzma"
1355   }
1356
1357   if { "$theOS" == "wnt" } {
1358     #  WinAPI libraries
1359     set aLibsMap(CSF_kernel32)     "kernel32"
1360     set aLibsMap(CSF_advapi32)     "advapi32"
1361     set aLibsMap(CSF_gdi32)        "gdi32"
1362     set aLibsMap(CSF_user32)       "user32 comdlg32"
1363     set aLibsMap(CSF_shell32)      "shell32"
1364     set aLibsMap(CSF_opengl32)     "opengl32"
1365     set aLibsMap(CSF_wsock32)      "wsock32"
1366     set aLibsMap(CSF_netapi32)     "netapi32"
1367     set aLibsMap(CSF_winmm)        "winmm"
1368     set aLibsMap(CSF_OpenGlLibs)   "opengl32"
1369     if { "$::HAVE_GLES2" == "true" } {
1370       set aLibsMap(CSF_OpenGlLibs) "libEGL libGLESv2"
1371     }
1372     set aLibsMap(CSF_psapi)        "Psapi"
1373     set aLibsMap(CSF_d3d9)         "d3d9"
1374
1375     # the naming is different on Windows
1376     set aLibsMap(CSF_TclLibs)      "tcl86"
1377     set aLibsMap(CSF_TclTkLibs)    "tk86"
1378
1379     set aLibsMap(CSF_QT)           "QtCore4 QtGui4"
1380
1381     # tbb headers define different pragma lib depending on debug/release
1382     set aLibsMap(CSF_TBB) ""
1383   } else {
1384     set aLibsMap(CSF_dl)           "dl"
1385     if { "$theOS" == "mac" || "$theOS" == "ios" } {
1386       set aLibsMap(CSF_objc)       "objc"
1387       if { "$theOS" == "ios" } {
1388         set aFrmsMap(CSF_Appkit)     "UIKit"
1389         set aFrmsMap(CSF_OpenGlLibs) "OpenGLES"
1390       } else {
1391         set aFrmsMap(CSF_Appkit)     "AppKit"
1392         set aFrmsMap(CSF_OpenGlLibs) "OpenGL"
1393       }
1394       set aFrmsMap(CSF_IOKit)      "IOKit"
1395       set aFrmsMap(CSF_TclLibs)    "Tcl"
1396       set aLibsMap(CSF_TclLibs)    ""
1397       set aFrmsMap(CSF_TclTkLibs)  "Tk"
1398       set aLibsMap(CSF_TclTkLibs)  ""
1399       set aLibsMap(CSF_QT)         "QtCore QtGui"
1400     } else {
1401       set aLibsMap(CSF_fontconfig) "fontconfig"
1402       if { "$theOS" == "qnx" } {
1403         # CSF_ThreadLibs - pthread API is part of libc on QNX
1404         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1405       } else {
1406         set aLibsMap(CSF_ThreadLibs) "pthread rt"
1407         set aLibsMap(CSF_OpenGlLibs) "GL"
1408         set aLibsMap(CSF_TclTkLibs)  "X11 tk8.6"
1409         set aLibsMap(CSF_XwLibs)     "X11 Xext Xmu Xi"
1410         set aLibsMap(CSF_MotifLibs)  "X11"
1411       }
1412
1413       if { "$::HAVE_GLES2" == "true" } {
1414         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1415       }
1416     }
1417   }
1418 }
1419
1420 # Returns string of library dependencies for generation of Visual Studio project or make lists.
1421 proc osutils:vtkCsf {{theOS ""}} {
1422   set aVtkVer "6.1"
1423
1424   set aPathSplitter ":"
1425   if {"$theOS" == "wnt"} {
1426     set aPathSplitter ";"
1427   }
1428
1429   set anOptIncs [split $::env(CSF_OPT_INC) "$aPathSplitter"]
1430   foreach anIncItem $anOptIncs {
1431     if {[regexp -- "vtk-(.*)$" [file tail $anIncItem] dummy aFoundVtkVer]} {
1432       set aVtkVer $aFoundVtkVer
1433     }
1434   }
1435
1436   set aLibArray [list vtkCommonCore vtkCommonDataModel vtkCommonExecutionModel vtkCommonMath vtkCommonTransforms vtkRenderingCore \
1437                       vtkRenderingOpenGL  vtkFiltersGeneral vtkIOCore vtkIOImage vtkImagingCore vtkInteractionStyle]
1438
1439   # Additional suffices for the libraries
1440   set anIdx 0
1441   foreach anItem $aLibArray {
1442     lset aLibArray $anIdx $anItem-$aVtkVer
1443     incr anIdx
1444   }
1445
1446   return [join $aLibArray " "]
1447 }
1448
1449 # @param theLibsList   - dependencies (libraries  list)
1450 # @param theFrameworks - dependencies (frameworks list, OS X specific)
1451 proc osutils:usedOsLibs { theToolKit theOS theLibsList theFrameworks } {
1452   global path
1453   upvar $theLibsList   aLibsList
1454   upvar $theFrameworks aFrameworks
1455   set aLibsList   [list]
1456   set aFrameworks [list]
1457
1458   osutils:csfList $theOS aLibsMap aFrmsMap
1459
1460   foreach aCsfElem [osutils:tk:csfInExternlib "$path/src/${theToolKit}/EXTERNLIB"] {
1461     if [info exists aLibsMap($aCsfElem)] {
1462       foreach aLib [split "$aLibsMap($aCsfElem)"] {
1463         if { [lsearch $aLibsList $aLib] == "-1" } {
1464           lappend aLibsList $aLib
1465         }
1466       }
1467     }
1468     if [info exists aFrmsMap($aCsfElem)] {
1469       foreach aFrm [split "$aFrmsMap($aCsfElem)"] {
1470         if { [lsearch $aFrameworks $aFrm] == "-1" } {
1471           lappend aFrameworks $aFrm
1472         }
1473       }
1474     }
1475   }
1476 }
1477
1478 # Returns liste of UD in a toolkit. tkloc is a full path wok.
1479 proc osutils:tk:units { tkloc } {
1480   global path
1481   set l {}
1482   set PACKAGES "$path/src/$tkloc/PACKAGES"
1483   foreach u [wokUtils:FILES:FileToList $PACKAGES] {
1484     if {[file isdirectory "$path/src/$u"]} {
1485       lappend l $u
1486     }
1487   }
1488   if { $l == {} } {
1489     ;#puts stderr "Warning. No devunit included in $tkloc"
1490   }
1491   return $l
1492 }
1493
1494 proc osutils:justwnt { listloc } {
1495   set goaway [list Xw]
1496   return [osutils:juststation $goaway $listloc]
1497 }
1498
1499 # remove from listloc OpenCascade units indesirables on NT
1500 proc osutils:juststation {goaway listloc} {
1501   global path
1502   set lret {}
1503   foreach u $listloc {
1504     if {([file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 )
1505      || (![file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 ) } {
1506       lappend lret $u
1507     }
1508   }
1509   return $lret
1510 }
1511
1512 # intersect3 - perform the intersecting of two lists, returning a list containing three lists.
1513 # The first list is everything in the first list that wasn't in the second,
1514 # the second list contains the intersection of the two lists, the third list contains everything
1515 # in the second list that wasn't in the first.
1516 proc osutils:intersect3 {list1 list2} {
1517   set la1(0) {} ; unset la1(0)
1518   set lai(0) {} ; unset lai(0)
1519   set la2(0) {} ; unset la2(0)
1520   foreach v $list1 {
1521     set la1($v) {}
1522   }
1523   foreach v $list2 {
1524     set la2($v) {}
1525   }
1526   foreach elem [concat $list1 $list2] {
1527     if {[info exists la1($elem)] && [info exists la2($elem)]} {
1528       unset la1($elem)
1529       unset la2($elem)
1530       set lai($elem) {}
1531     }
1532   }
1533   list [lsort [array names la1]] [lsort [array names lai]] [lsort [array names la2]]
1534 }
1535
1536 # Prepare relative path
1537 proc relativePath {thePathFrom thePathTo} {
1538   if { [file isdirectory "$thePathFrom"] == 0 } {
1539     return ""
1540   }
1541
1542   set aPathFrom [file normalize "$thePathFrom"]
1543   set aPathTo   [file normalize "$thePathTo"]
1544
1545   set aCutedPathFrom "${aPathFrom}/dummy"
1546   set aRelatedDeepPath ""
1547
1548   while { "$aCutedPathFrom" != [file normalize "$aCutedPathFrom/.."] } {
1549     set aCutedPathFrom [file normalize "$aCutedPathFrom/.."]
1550     # does aPathTo contain aCutedPathFrom?
1551     regsub -all $aCutedPathFrom $aPathTo "" aPathFromAfterCut
1552     if { "$aPathFromAfterCut" != "$aPathTo" } { # if so
1553       if { "$aCutedPathFrom" == "$aPathFrom" } { # just go higher, for example, ./somefolder/someotherfolder
1554         set aPathTo ".${aPathTo}"
1555       } elseif { "$aCutedPathFrom" == "$aPathTo" } { # remove the last "/"
1556         set aRelatedDeepPath [string replace $aRelatedDeepPath end end ""]
1557       }
1558       regsub -all $aCutedPathFrom $aPathTo $aRelatedDeepPath aPathToAfterCut
1559       regsub -all "//" $aPathToAfterCut "/" aPathToAfterCut
1560       return $aPathToAfterCut
1561     }
1562     set aRelatedDeepPath "$aRelatedDeepPath../"
1563
1564   }
1565
1566   return $thePathTo
1567 }
1568
1569 proc wokUtils:EASY:bs1 { s } {
1570     regsub -all {/} $s {\\} r
1571     return $r
1572 }
1573
1574 # Returs for a full path the liste of n last directory part
1575 # n = 1 => tail
1576 # n = 2 => dir/file.c
1577 # n = 3 => sdir/dir/file.c
1578 # etc..
1579 proc wokUtils:FILES:wtail { f n } {
1580     set ll [expr [llength [set lif [file split $f]]] -$n]
1581     return [join [lrange $lif $ll end] /]
1582 }
1583
1584 # Generate entry for one source file in Visual Studio 10 project file
1585 proc osutils:vcxproj:cxxfile { theFile theParams } {
1586   if { $theParams == "" } {
1587     return "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\" />\n"
1588   }
1589
1590   set aParams [string trim ${theParams}]
1591   append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
1592   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1593   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1594   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1595   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1596   append text "    </ClCompile>\n"
1597   return $text
1598 }
1599
1600 # Generate entry for one header file in Visual Studio 10 project file
1601 proc osutils:vcxproj:hxxfile { theFile } { return "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\" />\n" }
1602
1603 # Generate Visual Studio 2010 project filters file
1604 proc osutils:vcxproj:filters { dir proj theCxxFilesMap theHxxFilesMap } {
1605   upvar $theCxxFilesMap aCxxFilesMap
1606   upvar $theHxxFilesMap aHxxFilesMap
1607
1608   # header
1609   append text "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
1610   append text "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
1611
1612   # list of "filters" (units)
1613   append text "  <ItemGroup>\n"
1614   append text "    <Filter Include=\"Source files\">\n"
1615   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1616   append text "    </Filter>\n"
1617   append text "    <Filter Include=\"Header files\">\n"
1618   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1619   append text "    </Filter>\n"
1620   foreach unit $aCxxFilesMap(units) {
1621     append text "    <Filter Include=\"Source files\\${unit}\">\n"
1622     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1623     append text "    </Filter>\n"
1624   }
1625   foreach unit $aHxxFilesMap(units) {
1626     append text "    <Filter Include=\"Header files\\${unit}\">\n"
1627     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1628     append text "    </Filter>\n"
1629   }
1630   append text "  </ItemGroup>\n"
1631
1632   # list of cxx files
1633   append text "  <ItemGroup>\n"
1634   foreach unit $aCxxFilesMap(units) {
1635     foreach file $aCxxFilesMap($unit) {
1636       append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1637       append text "      <Filter>Source files\\${unit}</Filter>\n"
1638       append text "    </ClCompile>\n"
1639     }
1640   }
1641   append text "  </ItemGroup>\n"
1642
1643   # list of hxx files
1644   append text "  <ItemGroup>\n"
1645   foreach unit $aHxxFilesMap(units) {
1646     foreach file $aHxxFilesMap($unit) {
1647       append text "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1648       append text "      <Filter>Header files\\${unit}</Filter>\n"
1649       append text "    </ClInclude>\n"
1650     }
1651   }
1652   append text "  </ItemGroup>\n"
1653
1654   append text "  <ItemGroup>\n"
1655   append text "    <ResourceCompile Include=\"${proj}.rc\" />\n"
1656   append text "  </ItemGroup>\n"
1657
1658   # end
1659   append text "</Project>"
1660
1661   # write file
1662   set fp [open [set fvcproj [file join $dir ${proj}.vcxproj.filters]] w]
1663   fconfigure $fp -translation crlf
1664   puts $fp $text
1665   close $fp
1666
1667   return ${proj}.vcxproj.filters
1668 }
1669
1670 # Generate RC file content for ToolKit from template
1671 proc osutils:readtemplate:rc {theOutDir theToolKit} {
1672   set aLoc "$::THE_CASROOT/adm/templates/template_dll.rc"
1673   set aBody [wokUtils:FILES:FileToString $aLoc]
1674   regsub -all -- {__TKNAM__} $aBody $theToolKit aBody
1675
1676   set aFile [open "${theOutDir}/${theToolKit}.rc" "w"]
1677   fconfigure $aFile -translation lf
1678   puts $aFile $aBody
1679   close $aFile
1680   return "${theOutDir}/${theToolKit}.rc"
1681 }
1682
1683 # Generate Visual Studio project file for ToolKit
1684 proc osutils:vcproj { theVcVer isUWP theOutDir theToolKit theGuidsMap } {
1685   set theProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 0]
1686
1687   set l_compilable [osutils:compilable wnt]
1688   regsub -all -- {__TKNAM__} $theProjTmpl $theToolKit theProjTmpl
1689
1690   upvar $theGuidsMap aGuidsMap
1691   if { ! [info exists aGuidsMap($theToolKit)] } {
1692     set aGuidsMap($theToolKit) [OS:genGUID]
1693   }
1694   regsub -all -- {__PROJECT_GUID__} $theProjTmpl $aGuidsMap($theToolKit) theProjTmpl
1695
1696   set theProjTmpl [osutils:uwp:proj $isUWP ${theProjTmpl}]
1697
1698   set aUsedLibs [list]
1699
1700   if { $isUWP } {
1701     lappend aUsedLibs "WindowsApp.lib"
1702   }
1703
1704   foreach tkx [osutils:commonUsedTK  $theToolKit] {
1705     lappend aUsedLibs "${tkx}.lib"
1706   }
1707
1708   osutils:usedOsLibs $theToolKit "wnt" aLibs aFrameworks
1709   foreach aLibIter $aLibs {
1710     lappend aUsedLibs "${aLibIter}.lib"
1711   }
1712
1713   # correct names of referred third-party libraries that are named with suffix
1714   # depending on VC version
1715   set aVCRTVer [string range $theVcVer 0 3]
1716   regsub -all -- {vc[0-9]+} $aUsedLibs $aVCRTVer aUsedLibs
1717
1718   # and put this list to project file
1719   #puts "$theToolKit requires  $aUsedLibs"
1720   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1721     set aUsedLibs [join $aUsedLibs {;}]
1722   }
1723   regsub -all -- {__TKDEP__} $theProjTmpl $aUsedLibs theProjTmpl
1724
1725   set anIncPaths "..\\..\\..\\inc"
1726 #  set aTKDefines ""
1727   set aFilesSection ""
1728   set aVcFilesCxx(units) ""
1729   set aVcFilesHxx(units) ""
1730   set listloc [osutils:tk:units $theToolKit]
1731   if [array exists written] { unset written }
1732   #puts "\t1 [wokparam -v %CMPLRS_CXX_Options [w_info -f]] father"
1733   #puts "\t2 [wokparam -v %CMPLRS_CXX_Options] branch"
1734   #puts "\t1 [wokparam -v %CMPLRS_C_Options [w_info -f]] father"
1735   #puts "\t2 [wokparam -v %CMPLRS_C_Options] branch"
1736   set fxloparamfcxx [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx f] [_get_options wnt cmplrs_cxx b]] 2]
1737   set fxloparamfc   [lindex [osutils:intersect3 [_get_options wnt cmplrs_c f] [_get_options wnt cmplrs_c b]] 2]
1738   set fxloparam ""
1739   foreach fxlo $listloc {
1740     set xlo $fxlo
1741     set aSrcFiles [osutils:tk:cxxfiles $xlo wnt]
1742         set aHxxFiles [osutils:tk:hxxfiles $xlo wnt]
1743         set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx $fxlo]
1744     if {$fxlo_cmplrs_options_cxx == ""} {
1745       set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx b]
1746     }
1747         set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c $fxlo]
1748     if {$fxlo_cmplrs_options_c == ""} {
1749       set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c b]
1750     }
1751     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx b] $fxlo_cmplrs_options_cxx] 2]"
1752     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_c b] $fxlo_cmplrs_options_c] 2]"
1753         #puts "\t3 [wokparam -v %CMPLRS_CXX_Options] branch CXX "
1754         #puts "\t4 [wokparam -v %CMPLRS_CXX_Options $fxlo] $fxlo  CXX"
1755         #puts "\t5 [wokparam -v %CMPLRS_C_Options] branch C"
1756         #puts "\t6 [wokparam -v %CMPLRS_C_Options   $fxlo] $fxlo  C"
1757     set needparam ""
1758     foreach partopt $fxloparam {
1759       if {[string first "-I" $partopt] == "0"} {
1760         # this is an additional includes search path
1761         continue
1762       }
1763       set needparam "$needparam $partopt"
1764     }
1765
1766     # Format of projects in vc10+ is different from vc7-9
1767     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1768       foreach aSrcFile [lsort $aSrcFiles] {
1769         if { ![info exists written([file tail $aSrcFile])] } {
1770           set written([file tail $aSrcFile]) 1
1771           append aFilesSection [osutils:vcxproj:cxxfile $aSrcFile $needparam]
1772         } else {
1773           puts "Warning : in vcproj more than one occurences for [file tail $aSrcFile]"
1774         }
1775         if { ! [info exists aVcFilesCxx($xlo)] } { lappend aVcFilesCxx(units) $xlo }
1776         lappend aVcFilesCxx($xlo) $aSrcFile
1777       }
1778       foreach aHxxFile [lsort $aHxxFiles] {
1779         if { ![info exists written([file tail $aHxxFile])] } {
1780           set written([file tail $aHxxFile]) 1
1781           append aFilesSection [osutils:vcxproj:hxxfile $aHxxFile]
1782         } else {
1783           puts "Warning : in vcproj more than one occurences for [file tail $aHxxFile]"
1784         }
1785         if { ! [info exists aVcFilesHxx($xlo)] } { lappend aVcFilesHxx(units) $xlo }
1786         lappend aVcFilesHxx($xlo) $aHxxFile
1787       }
1788     } else {
1789       append aFilesSection "\t\t\t<Filter\n"
1790       append aFilesSection "\t\t\t\tName=\"${xlo}\"\n"
1791       append aFilesSection "\t\t\t\t>\n"
1792       foreach aSrcFile [lsort $aSrcFiles] {
1793         if { ![info exists written([file tail $aSrcFile])] } {
1794           set written([file tail $aSrcFile]) 1
1795           append aFilesSection [osutils:vcproj:file $theVcVer $aSrcFile $needparam]
1796         } else {
1797           puts "Warning : in vcproj more than one occurences for [file tail $aSrcFile]"
1798         }
1799       }
1800       append aFilesSection "\t\t\t</Filter>\n"
1801     }
1802   }
1803
1804   regsub -all -- {__TKINC__}  $theProjTmpl $anIncPaths theProjTmpl
1805   regsub -all -- {__FILES__}  $theProjTmpl $aFilesSection theProjTmpl
1806
1807   # write file
1808   set aFile [open [set aVcFiles [file join $theOutDir ${theToolKit}.[osutils:vcproj:ext $theVcVer]]] w]
1809   fconfigure $aFile -translation crlf
1810   puts $aFile $theProjTmpl
1811   close $aFile
1812
1813   # write filters file for vc10+
1814   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1815     lappend aVcFiles [osutils:vcxproj:filters $theOutDir $theToolKit aVcFilesCxx aVcFilesHxx]
1816   }
1817
1818   # write resource file
1819   lappend aVcFiles [osutils:readtemplate:rc $theOutDir $theToolKit]
1820
1821   return $aVcFiles
1822 }
1823
1824 # for a unit returns a map containing all its file in the current
1825 # workbench
1826 # local = 1 only local files
1827 proc osutils:tk:loadunit { loc map } {
1828   #puts $loc
1829   upvar $map TLOC
1830   catch { unset TLOC }
1831   set lfiles [_get_used_files $loc]
1832   foreach f $lfiles {
1833     #puts "\t$f"
1834     set t [lindex $f 0]
1835     set p [lindex $f 2]
1836     if [info exists TLOC($t)] {
1837       set l $TLOC($t)
1838       lappend l $p
1839       set TLOC($t) $l
1840     } else {
1841       set TLOC($t) $p
1842     }
1843   }
1844   return
1845 }
1846
1847 # Returns the list of all files name in a toolkit within specified list of file extensions.
1848 proc osutils:tk:files { tkloc theExtensions } {
1849   set Tfiles(source,nocdlpack)     {source pubinclude}
1850   set Tfiles(source,toolkit)       {}
1851   set Tfiles(source,executable)    {source pubinclude}
1852   set listloc [concat [osutils:tk:units $tkloc] $tkloc]
1853   #puts " listloc = $listloc"
1854
1855   set resultloc $listloc
1856   set lret {}
1857   foreach loc $resultloc {
1858     set utyp [_get_type $loc]
1859     #puts "\"$utyp\" \"$loc\""
1860     switch $utyp {
1861          "t" { set utyp "toolkit" }
1862          "n" { set utyp "nocdlpack" }
1863          "x" { set utyp "executable" }
1864          default { error "Error: Cannot determine type of unit $loc, check adm/UDLIST!" }
1865     }
1866     if [array exists map] { unset map }
1867     osutils:tk:loadunit $loc map
1868     #puts " loc = $loc === > [array names map]"
1869     set LType $Tfiles(source,${utyp})
1870     foreach typ [array names map] {
1871       if { [lsearch $LType $typ] == -1 } {
1872         unset map($typ)
1873       }
1874     }
1875     foreach type [array names map] {
1876       #puts $type
1877       foreach f $map($type) {
1878         #puts $f
1879         if { [lsearch $theExtensions [file extension $f]] != -1 } {
1880           lappend lret $f
1881         }
1882       }
1883     }
1884   }
1885   return $lret
1886 }
1887
1888 # Returns the list of all compilable files name in a toolkit.
1889 proc osutils:tk:cxxfiles { tkloc thePlatform } { return [osutils:tk:files $tkloc [osutils:compilable $thePlatform]] }
1890
1891 # Returns the list of all header files name in a toolkit.
1892 proc osutils:tk:hxxfiles { tkloc thePlatform } { return [osutils:tk:files $tkloc [osutils:fileExtensionsHeaders $thePlatform]] }
1893
1894 # Generate Visual Studio project file for executable
1895 proc osutils:vcprojx { theVcVer isUWP theOutDir theToolKit theGuidsMap } {
1896   set aVcFiles {}
1897   foreach f [osutils:tk:cxxfiles $theToolKit wnt] {
1898     set aProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 1]
1899
1900     set aProjName [file rootname [file tail $f]]
1901     set l_compilable [osutils:compilable wnt]
1902     regsub -all -- {__XQTNAM__} $aProjTmpl $aProjName aProjTmpl
1903
1904     upvar $theGuidsMap aGuidsMap
1905     if { ! [info exists aGuidsMap($aProjName)] } {
1906       set aGuidsMap($aProjName) [OS:genGUID]
1907     }
1908     regsub -all -- {__PROJECT_GUID__} $aProjTmpl $aGuidsMap($aProjName) aProjTmpl
1909
1910     set aUsedLibs [list]
1911     foreach tkx [osutils:commonUsedTK  $theToolKit] {
1912       lappend aUsedLibs "${tkx}.lib"
1913     }
1914
1915     osutils:usedOsLibs $theToolKit "wnt" aLibs aFrameworks
1916     foreach aLibIter $aLibs {
1917       lappend aUsedLibs "${aLibIter}.lib"
1918     }
1919
1920     # correct names of referred third-party libraries that are named with suffix
1921     # depending on VC version
1922     set aVCRTVer [string range $theVcVer 0 3]
1923     regsub -all -- {vc[0-9]+} $aUsedLibs $aVCRTVer aUsedLibs
1924
1925 #    puts "$aProjName requires  $aUsedLibs"
1926     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1927       set aUsedLibs [join $aUsedLibs {;}]
1928     }
1929     regsub -all -- {__TKDEP__} $aProjTmpl $aUsedLibs aProjTmpl
1930
1931     set aFilesSection ""
1932     set aVcFilesCxx(units) ""
1933         set aVcFilesHxx(units) ""
1934
1935     if { ![info exists written([file tail $f])] } {
1936       set written([file tail $f]) 1
1937
1938       if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1939         append aFilesSection [osutils:vcxproj:cxxfile $f ""]
1940         if { ! [info exists aVcFilesCxx($theToolKit)] } { lappend aVcFilesCxx(units) $theToolKit }
1941         lappend aVcFilesCxx($theToolKit) $f
1942       } else {
1943         append aFilesSection "\t\t\t<Filter\n"
1944         append aFilesSection "\t\t\t\tName=\"$theToolKit\"\n"
1945         append aFilesSection "\t\t\t\t>\n"
1946         append aFilesSection [osutils:vcproj:file $theVcVer $f ""]
1947         append aFilesSection "\t\t\t</Filter>"
1948       }
1949     } else {
1950       puts "Warning : in vcproj there are than one occurences for [file tail $f]"
1951     }
1952     #puts "$aProjTmpl $aFilesSection"
1953     set anIncPaths "..\\..\\..\\inc"
1954     regsub -all -- {__TKINC__}  $aProjTmpl $anIncPaths    aProjTmpl
1955     regsub -all -- {__FILES__}  $aProjTmpl $aFilesSection aProjTmpl
1956     regsub -all -- {__CONF__}   $aProjTmpl Application    aProjTmpl
1957
1958     regsub -all -- {__XQTEXT__} $aProjTmpl "exe" aProjTmpl
1959
1960     set aFile [open [set aVcFilePath [file join $theOutDir ${aProjName}.[osutils:vcproj:ext $theVcVer]]] w]
1961     fconfigure $aFile -translation crlf
1962     puts $aFile $aProjTmpl
1963     close $aFile
1964
1965     set aCommonSettingsFile "$aVcFilePath.user"
1966     lappend aVcFiles $aVcFilePath
1967
1968     # write filters file for vc10
1969     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1970       lappend aVcFiles [osutils:vcxproj:filters $theOutDir $aProjName aVcFilesCxx aVcFilesHxx]
1971     }
1972
1973     # write resource file
1974     lappend aVcFiles [osutils:readtemplate:rc $theOutDir $aProjName]
1975
1976     set aCommonSettingsFileTmpl ""
1977     if { "$theVcVer" == "vc7" || "$theVcVer" == "vc8" } {
1978       # nothing
1979     } elseif { "$theVcVer" == "vc9" } {
1980       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcproj.user.vc9x"]
1981     } else {
1982       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcxproj.user.vc10x"]
1983     }
1984     if { "$aCommonSettingsFileTmpl" != "" } {
1985       regsub -all -- {__VCVER__} $aCommonSettingsFileTmpl $aVCRTVer aCommonSettingsFileTmpl
1986
1987       set aFile [open [set aVcFilePath "$aCommonSettingsFile"] w]
1988       fconfigure $aFile -translation crlf
1989       puts $aFile $aCommonSettingsFileTmpl
1990       close $aFile
1991
1992       lappend aVcFiles "$aCommonSettingsFile"
1993     }
1994   }
1995   return $aVcFiles
1996 }
1997
1998 # Generate entry for one source file in Visual Studio 7 - 9 project file
1999 proc osutils:vcproj:file { theVcVer theFile theOptions } {
2000   append aText "\t\t\t\t<File\n"
2001   append aText "\t\t\t\t\tRelativePath=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
2002   if { $theOptions == "" } {
2003     append aText "\t\t\t\t</File>\n"
2004     return $aText
2005   }
2006
2007   append aText "\t\t\t\t\t<FileConfiguration\n"
2008   append aText "\t\t\t\t\t\tName=\"Release\|Win32\">\n"
2009   append aText "\t\t\t\t\t\t<Tool\n"
2010   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2011   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2012   foreach aParam $theOptions {
2013     append aText "$aParam "
2014   }
2015   append aText "\"\n"
2016   append aText "\t\t\t\t\t\t/>\n"
2017   append aText "\t\t\t\t\t</FileConfiguration>\n"
2018
2019   append aText "\t\t\t\t\t<FileConfiguration\n"
2020   append aText "\t\t\t\t\t\tName=\"Debug\|Win32\">\n"
2021   append aText "\t\t\t\t\t\t<Tool\n"
2022   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2023   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2024   foreach aParam $theOptions {
2025     append aText "$aParam "
2026   }
2027   append aText "\"\n"
2028   append aText "\t\t\t\t\t\t/>\n"
2029   append aText "\t\t\t\t\t</FileConfiguration>\n"
2030   if { "$theVcVer" == "vc7" } {
2031     append aText "\t\t\t\t</File>\n"
2032     return $aText
2033   }
2034
2035   append aText "\t\t\t\t\t<FileConfiguration\n"
2036   append aText "\t\t\t\t\t\tName=\"Release\|x64\">\n"
2037   append aText "\t\t\t\t\t\t<Tool\n"
2038   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2039   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2040   foreach aParam $theOptions {
2041     append aText "$aParam "
2042   }
2043   append aText "\"\n"
2044   append aText "\t\t\t\t\t\t/>\n"
2045   append aText "\t\t\t\t\t</FileConfiguration>\n"
2046
2047   append aText "\t\t\t\t\t<FileConfiguration\n"
2048   append aText "\t\t\t\t\t\tName=\"Debug\|x64\">\n"
2049   append aText "\t\t\t\t\t\t<Tool\n"
2050   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2051   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2052   foreach aParam $theOptions {
2053     append aText "$aParam "
2054   }
2055   append aText "\"\n"
2056   append aText "\t\t\t\t\t\t/>\n"
2057   append aText "\t\t\t\t\t</FileConfiguration>\n"
2058
2059   append aText "\t\t\t\t</File>\n"
2060   return $aText
2061 }
2062
2063 proc wokUtils:FILES:mkdir { d } {
2064     global tcl_version
2065     regsub -all {\.[^.]*} $tcl_version "" major
2066     if { $major == 8 } {
2067         file mkdir $d
2068     } else {
2069         if ![file exists $d] {
2070             if { "[info command mkdir]" == "mkdir" } {
2071                 mkdir -path $d
2072             } else {
2073                 puts stderr "wokUtils:FILES:mkdir : Error unable to find a mkdir command."
2074             }
2075         }
2076     }
2077     if [file exists $d] {
2078         return $d
2079     } else {
2080         return {}
2081     }
2082 }
2083
2084 # remove from listloc OpenCascade units indesirables on Unix
2085 proc osutils:justunix { listloc } {
2086   if { "$::tcl_platform(os)" == "Darwin" } {
2087     set goaway [list Xw WNT]
2088   } else {
2089     set goaway [list WNT]
2090   }
2091   return [osutils:juststation $goaway $listloc]
2092 }
2093
2094
2095 ####### CODEBLOCK ###################################################################
2096 # Function to generate Code Blocks workspace and project files
2097 proc OS:MKCBP { theOutDir theModules theAllSolution thePlatform theCmpl } {
2098   puts stderr "Generating project files for Code Blocks"
2099
2100   # Generate projects for toolkits and separate workspace for each module
2101   foreach aModule $theModules {
2102     OS:cworkspace          $aModule $aModule $theOutDir
2103     OS:cbp        $theCmpl $aModule          $theOutDir $thePlatform
2104   }
2105
2106   # Generate single workspace "OCCT" containing projects from all modules
2107   if { "$theAllSolution" != "" } {
2108     OS:cworkspace $theAllSolution $theModules $theOutDir
2109   }
2110
2111   puts "The Code Blocks workspace and project files are stored in the $theOutDir directory"
2112 }
2113
2114 # Generate Code Blocks projects
2115 proc OS:cbp { theCmpl theModules theOutDir thePlatform } {
2116   set aProjectFiles {}
2117   foreach aModule $theModules {
2118     foreach aToolKit [${aModule}:toolkits] {
2119       lappend aProjectFiles [osutils:cbptk $theCmpl $theOutDir $aToolKit $thePlatform]
2120     }
2121     foreach anExecutable [OS:executable ${aModule}] {
2122       lappend aProjectFiles [osutils:cbpx  $theCmpl $theOutDir $anExecutable $thePlatform]
2123     }
2124   }
2125   return $aProjectFiles
2126 }
2127
2128 # Generate Code::Blocks project file for ToolKit
2129 proc osutils:cbptk { theCmpl theOutDir theToolKit thePlatform} {
2130   set aUsedLibs     [list]
2131   set aFrameworks   [list]
2132   set anIncPaths    [list]
2133   set aTKDefines    [list]
2134   set aTKSrcFiles   [list]
2135
2136   # collect list of referred libraries to link with
2137   osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks
2138   set aDepToolkits [wokUtils:LIST:Purge [osutils:tk:close $theToolKit]]
2139   foreach tkx $aDepToolkits {
2140     lappend aUsedLibs "${tkx}"
2141   }
2142
2143   lappend anIncPaths "../../../inc"
2144   set listloc [osutils:tk:units $theToolKit]
2145
2146   if { [llength $listloc] == 0 } {
2147     set listloc $theToolKit
2148   }
2149
2150   if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2151     set resultloc [osutils:justwnt  $listloc]
2152   } else {
2153     set resultloc [osutils:justunix $listloc]
2154   }
2155   if [array exists written] { unset written }
2156   foreach fxlo $resultloc {
2157     set xlo       $fxlo
2158     set aSrcFiles [osutils:tk:cxxfiles $xlo $thePlatform]
2159     foreach aSrcFile [lsort $aSrcFiles] {
2160       if { ![info exists written([file tail $aSrcFile])] } {
2161         set written([file tail $aSrcFile]) 1
2162         lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2163       } else {
2164         puts "Warning : more than one occurences for [file tail $aSrcFile]"
2165       }
2166     }
2167
2168     # macros for correct DLL exports
2169 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2170 #      lappend aTKDefines "__${xlo}_DLL"
2171 #    }
2172   }
2173
2174   return [osutils:cbp $theCmpl $theOutDir $theToolKit $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines]
2175 }
2176
2177 # Generates Code Blocks workspace.
2178 proc OS:cworkspace { theSolName theModules theOutDir } {
2179   global path
2180   set aWsFilePath "${theOutDir}/${theSolName}.workspace"
2181   set aFile [open $aWsFilePath "w"]
2182   set isActiveSet 0
2183   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2184   puts $aFile "<CodeBlocks_workspace_file>"
2185   puts $aFile "\t<Workspace title=\"${theSolName}\">"
2186
2187   # collect list of projects to be created
2188   foreach aModule $theModules {
2189     # toolkits
2190     foreach aToolKit [osutils:tk:sort [${aModule}:toolkits]] {
2191       set aDependencies [LibToLink $aToolKit]
2192       if { [llength $aDependencies] == 0 } {
2193         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" />"
2194       } else {
2195         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" >"
2196         foreach aDepTk $aDependencies {
2197           puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2198         }
2199         puts $aFile "\t\t</Project>"
2200       }
2201     }
2202
2203     # executables, assume one project per cxx file...
2204     foreach aUnit [OS:executable ${aModule}] {
2205       set aUnitLoc $aUnit
2206       set src_files [_get_used_files $aUnit false]
2207       set aSrcFiles {}
2208       foreach s $src_files { 
2209         regexp {source ([^\s]+)} $s dummy name
2210         lappend aSrcFiles $name
2211       }
2212       foreach aSrcFile $aSrcFiles {
2213         set aFileExtension [file extension $aSrcFile]
2214         if { $aFileExtension == ".cxx" } {
2215           set aPrjName [file rootname $aSrcFile]
2216           set aDependencies [list]
2217           if {[file isdirectory $path/src/$aUnitLoc]} {
2218             set aDependencies [LibToLinkX $aUnitLoc [file rootname $aSrcFile]]
2219           }
2220           set anActiveState ""
2221           if { $isActiveSet == 0 } {
2222             set anActiveState " active=\"1\""
2223             set isActiveSet 1
2224           }
2225           if { [llength $aDependencies] == 0 } {
2226             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}/>"
2227           } else {
2228             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}>"
2229             foreach aDepTk $aDependencies {
2230               puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2231             }
2232             puts $aFile "\t\t</Project>"
2233           }
2234         }
2235       }
2236     }
2237   }
2238
2239   puts $aFile "\t</Workspace>"
2240   puts $aFile "</CodeBlocks_workspace_file>"
2241   close $aFile
2242
2243   return $aWsFilePath
2244 }
2245
2246 # Generate Code::Blocks project file for Executable
2247 proc osutils:cbpx { theCmpl theOutDir theToolKit thePlatform } {
2248   global path
2249   set aWokArch    "$::env(ARCH)"
2250
2251   set aCbpFiles {}
2252   foreach aSrcFile [osutils:tk:cxxfiles $theToolKit $thePlatform] {
2253     # collect list of referred libraries to link with
2254     set aUsedLibs     [list]
2255     set aFrameworks   [list]
2256     set anIncPaths    [list]
2257     set aTKDefines    [list]
2258     set aTKSrcFiles   [list]
2259     set aProjName [file rootname [file tail $aSrcFile]]
2260
2261     osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks
2262
2263     set aDepToolkits [LibToLinkX $theToolKit $aProjName]
2264     foreach tkx $aDepToolkits {
2265       if {[_get_type $tkx] == "t"} {
2266         lappend aUsedLibs "${tkx}"
2267       }
2268       if {[lsearch [glob -tails -directory "$path/src" -types d *] $tkx] == "-1"} {
2269         lappend aUsedLibs "${tkx}"
2270       }
2271     }
2272
2273     set WOKSteps_exec_link [_get_options lin WOKSteps_exec_link $theToolKit]
2274     if { [regexp {WOKStep_DLLink} $WOKSteps_exec_link] || [regexp {WOKStep_Libink} $WOKSteps_exec_link] } {
2275       set isExecutable "false"
2276     } else {
2277       set isExecutable "true"
2278     }
2279
2280     if { ![info exists written([file tail $aSrcFile])] } {
2281       set written([file tail $aSrcFile]) 1
2282       lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2283     } else {
2284       puts "Warning : in cbp there are more than one occurences for [file tail $aSrcFile]"
2285     }
2286
2287     # macros for correct DLL exports
2288 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2289 #      lappend aTKDefines "__${theToolKit}_DLL"
2290 #    }
2291
2292     # common include paths
2293     lappend anIncPaths "../../../inc"
2294
2295     lappend aCbpFiles [osutils:cbp $theCmpl $theOutDir $aProjName $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines $isExecutable]
2296   }
2297
2298   return $aCbpFiles
2299 }
2300
2301 # This function intended to generate Code::Blocks project file
2302 # @param theCmpl       - the compiler (gcc or msvc)
2303 # @param theOutDir     - output directory to place project file
2304 # @param theProjName   - project name
2305 # @param theSrcFiles   - list of source files
2306 # @param theLibsList   - dependencies (libraries  list)
2307 # @param theFrameworks - dependencies (frameworks list, Mac OS X specific)
2308 # @param theIncPaths   - header search paths
2309 # @param theDefines    - compiler macro definitions
2310 # @param theIsExe      - flag to indicate executable / library target
2311 proc osutils:cbp { theCmpl theOutDir theProjName thePlatform theSrcFiles theLibsList theFrameworks theIncPaths theDefines {theIsExe "false"} } {
2312   set aWokArch    "$::env(ARCH)"
2313
2314   set aCmplCbp "gcc"
2315   set aCmplFlags        [list]
2316   set aCmplFlagsRelease [list]
2317   set aCmplFlagsDebug   [list]
2318   set toPassArgsByFile 0
2319   set aLibPrefix "lib"
2320   set aPlatformAndCompiler "${thePlatform}/gcc"
2321   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } {
2322     set aPlatformAndCompiler "${thePlatform}/clang"
2323   }
2324   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" || "$thePlatform" == "qnx" } {
2325     set toPassArgsByFile 1
2326   }
2327   if { "$theCmpl" == "msvc" } {
2328     set aCmplCbp "msvc8"
2329     set aLibPrefix ""
2330   }
2331
2332   if { "$theCmpl" == "msvc" } {
2333     set aCmplFlags        "-arch:SSE2 -EHsc -W4 -MP"
2334     set aCmplFlagsRelease "-MD  -O2"
2335     set aCmplFlagsDebug   "-MDd -Od -Zi"
2336     lappend aCmplFlags    "-D_CRT_SECURE_NO_WARNINGS"
2337     lappend aCmplFlags    "-D_CRT_NONSTDC_NO_DEPRECATE"
2338   } elseif { "$theCmpl" == "gcc" } {
2339     if { "$thePlatform" != "qnx" } {
2340       set aCmplFlags      "-mmmx -msse -msse2 -mfpmath=sse"
2341     }
2342     set aCmplFlagsRelease "-O2"
2343     set aCmplFlagsDebug   "-O0 -g"
2344     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2345       lappend aCmplFlags "-std=gnu++0x"
2346       lappend aCmplFlags "-D_WIN32_WINNT=0x0501"
2347     } else {
2348       lappend aCmplFlags "-std=c++0x"
2349       lappend aCmplFlags "-fPIC"
2350       lappend aCmplFlags "-DOCC_CONVERT_SIGNALS"
2351     }
2352     lappend aCmplFlags   "-Wall"
2353     lappend aCmplFlags   "-fexceptions"
2354   }
2355   lappend aCmplFlagsRelease "-DNDEBUG"
2356   lappend aCmplFlagsRelease "-DNo_Exception"
2357   lappend aCmplFlagsDebug   "-D_DEBUG"
2358   if { "$thePlatform" == "qnx" } {
2359     lappend aCmplFlags "-D_QNX_SOURCE"
2360   }
2361
2362   set aCbpFilePath    "${theOutDir}/${theProjName}.cbp"
2363   set aLnkFileName    "${theProjName}_obj.link"
2364   set aLnkDebFileName "${theProjName}_objd.link"
2365   set aLnkFilePath    "${theOutDir}/${aLnkFileName}"
2366   set aLnkDebFilePath "${theOutDir}/${aLnkDebFileName}"
2367   set aFile [open $aCbpFilePath "w"]
2368   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2369   puts $aFile "<CodeBlocks_project_file>"
2370   puts $aFile "\t<FileVersion major=\"1\" minor=\"6\" />"
2371   puts $aFile "\t<Project>"
2372   puts $aFile "\t\t<Option title=\"$theProjName\" />"
2373   puts $aFile "\t\t<Option pch_mode=\"2\" />"
2374   puts $aFile "\t\t<Option compiler=\"$aCmplCbp\" />"
2375   puts $aFile "\t\t<Build>"
2376
2377   # Release target configuration
2378   puts $aFile "\t\t\t<Target title=\"Release\">"
2379   if { "$theIsExe" == "true" } {
2380     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bin/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2381     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2382   } else {
2383     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2384       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bin/${aLibPrefix}${theProjName}\" imp_lib=\"../../../${aPlatformAndCompiler}/lib/\$(TARGET_OUTPUT_BASENAME)\" prefix_auto=\"1\" extension_auto=\"1\" />"
2385     } else {
2386       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/lib/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2387     }
2388     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2389   }
2390   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/obj\" />"
2391   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2392   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2393   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2394     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2395   } else {
2396     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2397   }
2398
2399   # compiler options per TARGET (including defines)
2400   puts $aFile "\t\t\t\t<Compiler>"
2401   foreach aFlagIter $aCmplFlagsRelease {
2402     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2403   }
2404   foreach aMacro $theDefines {
2405     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2406   }
2407   puts $aFile "\t\t\t\t</Compiler>"
2408
2409   puts $aFile "\t\t\t\t<Linker>"
2410   if { $toPassArgsByFile == 1 } {
2411     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkFileName\" />"
2412   }
2413   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/lib\" />"
2414   if { "$thePlatform" == "mac" } {
2415     if { [ lsearch $theLibsList X11 ] >= 0} {
2416       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2417     }
2418   }
2419   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch})\" />"
2420   if { "$thePlatform" == "lin" } {
2421     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/lib\" />"
2422   }
2423   puts $aFile "\t\t\t\t</Linker>"
2424
2425   puts $aFile "\t\t\t</Target>"
2426
2427   # Debug target configuration
2428   puts $aFile "\t\t\t<Target title=\"Debug\">"
2429   if { "$theIsExe" == "true" } {
2430     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bind/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2431     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2432   } else {
2433     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2434       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bind/${aLibPrefix}${theProjName}\" imp_lib=\"../../../${aPlatformAndCompiler}/libd/\$(TARGET_OUTPUT_BASENAME)\" prefix_auto=\"1\" extension_auto=\"1\" />"
2435     } else {
2436       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/libd/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2437     }
2438     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2439   }
2440   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/objd\" />"
2441   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2442   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2443   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2444     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2445   } else {
2446     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2447   }
2448
2449   # compiler options per TARGET (including defines)
2450   puts $aFile "\t\t\t\t<Compiler>"
2451   foreach aFlagIter $aCmplFlagsDebug {
2452     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2453   }
2454   foreach aMacro $theDefines {
2455     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2456   }
2457   puts $aFile "\t\t\t\t</Compiler>"
2458
2459   puts $aFile "\t\t\t\t<Linker>"
2460   if { $toPassArgsByFile == 1 } {
2461     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkDebFileName\" />"
2462   }
2463   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/libd\" />"
2464   if { "$thePlatform" == "mac" } {
2465     if { [ lsearch $theLibsList X11 ] >= 0} {
2466       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2467     }
2468   }
2469   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch}D)\" />"
2470   if { "$thePlatform" == "lin" } {
2471     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/libd\" />"
2472   }
2473   puts $aFile "\t\t\t\t</Linker>"
2474
2475   puts $aFile "\t\t\t</Target>"
2476
2477   puts $aFile "\t\t</Build>"
2478
2479   # COMMON compiler options
2480   puts $aFile "\t\t<Compiler>"
2481   foreach aFlagIter $aCmplFlags {
2482     puts $aFile "\t\t\t<Add option=\"$aFlagIter\" />"
2483   }
2484   puts $aFile "\t\t\t<Add option=\"\$(CSF_OPT_CMPL)\" />"
2485   foreach anIncPath $theIncPaths {
2486     puts $aFile "\t\t\t<Add directory=\"$anIncPath\" />"
2487   }
2488   puts $aFile "\t\t</Compiler>"
2489
2490   # COMMON linker options
2491   puts $aFile "\t\t<Linker>"
2492   if { "$thePlatform" == "wnt" && "$theCmpl" == "gcc" } {
2493     puts $aFile "\t\t\t<Add option=\"-Wl,--export-all-symbols\" />"
2494   }
2495   foreach aFrameworkName $theFrameworks {
2496     if { "$aFrameworkName" != "" } {
2497       puts $aFile "\t\t\t<Add option=\"-framework $aFrameworkName\" />"
2498     }
2499   }
2500   foreach aLibName $theLibsList {
2501     if { "$aLibName" != "" } {
2502       if { "$theCmpl" == "msvc" } {
2503         puts $aFile "\t\t\t<Add library=\"${aLibName}.lib\" />"
2504       } else {
2505         puts $aFile "\t\t\t<Add library=\"${aLibName}\" />"
2506       }
2507     }
2508   }
2509   puts $aFile "\t\t</Linker>"
2510
2511   # list of sources
2512
2513   set aFileLnkObj ""
2514   set aFileLnkObjd ""
2515   set isFirstSrcFile 1
2516   if { $toPassArgsByFile == 1 } {
2517     set aFileLnkObj  [open $aLnkFilePath    "w"]
2518     set aFileLnkObjd [open $aLnkDebFilePath "w"]
2519   }
2520
2521   foreach aSrcFile $theSrcFiles {
2522     if {[string equal -nocase [file extension $aSrcFile] ".mm"]} {
2523       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2524       puts $aFile "\t\t\t<Option compile=\"1\" />"
2525       puts $aFile "\t\t\t<Option link=\"1\" />"
2526       puts $aFile "\t\t</Unit>"
2527     } elseif {[string equal -nocase [file extension $aSrcFile] ".c"]} {
2528       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2529       puts $aFile "\t\t\t<Option compilerVar=\"CC\" />"
2530       puts $aFile "\t\t</Unit>"
2531     } elseif { $toPassArgsByFile == 1 && $isFirstSrcFile == 0 && [string equal -nocase [file extension $aSrcFile] ".cxx" ] } {
2532       # pass at list single source file to Code::Blocks as is
2533       # and pack the list of other files into the dedicated file to workaround process arguments limits on systems like Windows
2534       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2535       puts $aFile "\t\t\t<Option link=\"0\" />"
2536       puts $aFile "\t\t</Unit>"
2537
2538       set aFileObj  [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/obj/src/"]  $aSrcFile]]
2539       set aFileObjd [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/objd/src/"] $aSrcFile]]
2540       puts -nonewline $aFileLnkObj  "$aFileObj "
2541       puts -nonewline $aFileLnkObjd "$aFileObjd "
2542     } else {
2543       puts $aFile "\t\t<Unit filename=\"$aSrcFile\" />"
2544       set isFirstSrcFile 0
2545     }
2546   }
2547
2548   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2549     close $aFileLnkObj
2550     close $aFileLnkObjd
2551   }
2552
2553   puts $aFile "\t</Project>"
2554   puts $aFile "</CodeBlocks_project_file>"
2555   close $aFile
2556
2557   return $aCbpFilePath
2558 }
2559
2560 # Define libraries to link using only EXTERNLIB file
2561 proc LibToLinkX {thePackage theDummyName} {
2562   set aToolKits [LibToLink $thePackage]
2563   return $aToolKits
2564 }
2565
2566 # Function to generate Xcode workspace and project files
2567 proc OS:MKXCD { theOutDir {theModules {}} {theAllSolution ""} {theLibType "dynamic"} {thePlatform ""} } {
2568
2569   puts stderr "Generating project files for Xcode"
2570
2571   # Generate projects for toolkits and separate workspace for each module
2572   foreach aModule $theModules {
2573     OS:xcworkspace $aModule $aModule $theOutDir
2574     OS:xcodeproj   $aModule          $theOutDir ::THE_GUIDS_LIST $theLibType $thePlatform
2575   }
2576
2577   # Generate single workspace "OCCT" containing projects from all modules
2578   if { "$theAllSolution" != "" } {
2579     OS:xcworkspace $theAllSolution $theModules $theOutDir
2580   }
2581 }
2582
2583 # Generates toolkits sections for Xcode workspace file.
2584 proc OS:xcworkspace:toolkits { theModule } {
2585   set aBuff ""
2586
2587   # Adding toolkits for module in workspace.
2588   foreach aToolKit [osutils:tk:sort [${theModule}:toolkits]] {
2589     append aBuff "         <FileRef\n"
2590     append aBuff "            location = \"group:${aToolKit}.xcodeproj\">\n"
2591     append aBuff "         </FileRef>\n"
2592   }
2593
2594   # Adding executables for module, assume one project per cxx file...
2595   foreach aUnit [OS:executable ${theModule}] {
2596     set aUnitLoc $aUnit
2597     set src_files [_get_used_files $aUnit false]
2598     set aSrcFiles {}
2599     foreach s $src_files {
2600       regexp {source ([^\s]+)} $s dummy name
2601       lappend aSrcFiles $name
2602     }
2603     foreach aSrcFile $aSrcFiles {
2604       set aFileExtension [file extension $aSrcFile]
2605       if { $aFileExtension == ".cxx" } {
2606         set aPrjName [file rootname $aSrcFile]
2607         append aBuff "         <FileRef\n"
2608         append aBuff "            location = \"group:${aPrjName}.xcodeproj\">\n"
2609         append aBuff "         </FileRef>\n"
2610       }
2611     }
2612   }
2613
2614   # Removing unnecessary newline character from the end.
2615   set aBuff [string replace $aBuff end end]
2616   return $aBuff
2617 }
2618
2619 # Generates workspace files for Xcode.
2620 proc OS:xcworkspace { theWorkspaceName theModules theOutDir } {
2621   # Creating workspace directory for Xcode.
2622   set aWorkspaceDir "${theOutDir}/${theWorkspaceName}.xcworkspace"
2623   wokUtils:FILES:mkdir $aWorkspaceDir
2624   if { ! [file exists $aWorkspaceDir] } {
2625     puts stderr "Error: Could not create workspace directory \"$aWorkspaceDir\""
2626     return
2627   }
2628
2629   # Creating workspace file.
2630   set aWsFilePath "${aWorkspaceDir}/contents.xcworkspacedata"
2631   set aFile [open $aWsFilePath "w"]
2632
2633   # Adding header and section for main Group.
2634   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
2635   puts $aFile "<Workspace"
2636   puts $aFile "   version = \"1.0\">"
2637   puts $aFile "   <Group"
2638   puts $aFile "      location = \"container:\""
2639   puts $aFile "      name = \"${theWorkspaceName}\">"
2640
2641   # Adding modules.
2642   if { [llength "$theModules"] > 1 } {
2643     foreach aModule $theModules {
2644       puts $aFile "      <Group"
2645       puts $aFile "         location = \"container:\""
2646       puts $aFile "         name = \"${aModule}\">"
2647       puts $aFile [OS:xcworkspace:toolkits $aModule]
2648       puts $aFile "      </Group>"
2649     }
2650   } else {
2651     puts $aFile [OS:xcworkspace:toolkits $theModules]
2652   }
2653
2654   # Adding footer.
2655   puts $aFile "   </Group>"
2656   puts $aFile "</Workspace>"
2657   close $aFile
2658 }
2659
2660 # Generates Xcode project files.
2661 proc OS:xcodeproj { theModules theOutDir theGuidsMap theLibType thePlatform} {
2662   upvar $theGuidsMap aGuidsMap
2663
2664   set isStatic 0
2665   if { "$theLibType" == "static" } {
2666     set isStatic 1
2667   } elseif { "$thePlatform" == "ios" } {
2668     set isStatic 1
2669   }
2670
2671   set aProjectFiles {}
2672   foreach aModule $theModules {
2673     foreach aToolKit [${aModule}:toolkits] {
2674       lappend aProjectFiles [osutils:xcdtk $theOutDir $aToolKit     aGuidsMap $isStatic $thePlatform "dylib"]
2675     }
2676     foreach anExecutable [OS:executable ${aModule}] {
2677       lappend aProjectFiles [osutils:xcdtk $theOutDir $anExecutable aGuidsMap $isStatic $thePlatform "executable"]
2678     }
2679   }
2680   return $aProjectFiles
2681 }
2682
2683 # Generates dependencies section for Xcode project files.
2684 proc osutils:xcdtk:deps {theToolKit theTargetType theGuidsMap theFileRefSection theDepsGuids theDepsRefGuids thePlatform theIsStatic} {
2685   upvar $theGuidsMap         aGuidsMap
2686   upvar $theFileRefSection   aFileRefSection
2687   upvar $theDepsGuids        aDepsGuids
2688   upvar $theDepsRefGuids     aDepsRefGuids
2689
2690   set aBuildFileSection ""
2691   set aUsedLibs         [wokUtils:LIST:Purge [osutils:tk:close $theToolKit]]
2692   set aDepToolkits      [lappend [wokUtils:LIST:Purge [osutils:tk:close $theToolKit]] $theToolKit]
2693
2694   if { "$theTargetType" == "executable" } {
2695     set aFile [osutils:tk:cxxfiles $theToolKit mac]
2696     set aProjName [file rootname [file tail $aFile]]
2697     set aDepToolkits [LibToLinkX $theToolKit $aProjName]
2698   }
2699
2700   set aLibExt "dylib"
2701   if { $theIsStatic == 1 } {
2702     set aLibExt "a"
2703     if { "$theTargetType" != "executable" } {
2704       return $aBuildFileSection
2705     }
2706   }
2707
2708   osutils:usedOsLibs $theToolKit $thePlatform aLibs aFrameworks
2709   set aUsedLibs [concat $aUsedLibs $aLibs]
2710   set aUsedLibs [concat $aUsedLibs $aFrameworks]
2711   foreach tkx $aUsedLibs {
2712     set aDepLib    "${tkx}_Dep"
2713     set aDepLibRef "${tkx}_DepRef"
2714
2715     if { ! [info exists aGuidsMap($aDepLib)] } {
2716       set aGuidsMap($aDepLib) [OS:genGUID "xcd"]
2717     }
2718     if { ! [info exists aGuidsMap($aDepLibRef)] } {
2719       set aGuidsMap($aDepLibRef) [OS:genGUID "xcd"]
2720     }
2721
2722     append aBuildFileSection "\t\t$aGuidsMap($aDepLib) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aDepLibRef) ; \};\n"
2723     if {[lsearch -nocase $aFrameworks $tkx] == -1} {
2724       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = file; name = lib${tkx}.${aLibExt}; path = lib${tkx}.${aLibExt}; sourceTree = \"<group>\"; \};\n"
2725     } else {
2726       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ${tkx}.framework; path = /System/Library/Frameworks/${tkx}.framework; sourceTree = \"<absolute>\"; \};\n"
2727     }
2728     append aDepsGuids        "\t\t\t\t$aGuidsMap($aDepLib) ,\n"
2729     append aDepsRefGuids     "\t\t\t\t$aGuidsMap($aDepLibRef) ,\n"
2730   }
2731
2732   return $aBuildFileSection
2733 }
2734
2735 # Generates PBXBuildFile and PBXGroup sections for project file.
2736 proc osutils:xcdtk:sources {theToolKit theTargetType theSrcFileRefSection theGroupSection thePackageGuids theSrcFileGuids theGuidsMap theIncPaths} {
2737   upvar $theSrcFileRefSection aSrcFileRefSection
2738   upvar $theGroupSection      aGroupSection
2739   upvar $thePackageGuids      aPackagesGuids
2740   upvar $theSrcFileGuids      aSrcFileGuids
2741   upvar $theGuidsMap          aGuidsMap
2742   upvar $theIncPaths          anIncPaths
2743
2744   set listloc [osutils:tk:units $theToolKit]
2745   set resultloc [osutils:justunix $listloc]
2746   set aBuildFileSection ""
2747   set aPackages [lsort -nocase $resultloc]
2748   if { "$theTargetType" == "executable" } {
2749     set aPackages [list "$theToolKit"]
2750   }
2751
2752   # Generating PBXBuildFile, PBXGroup sections and groups for each package.
2753   foreach fxlo $aPackages {
2754     set xlo       $fxlo
2755     set aPackage "${xlo}_Package"
2756     set aSrcFileRefGuids ""
2757     if { ! [info exists aGuidsMap($aPackage)] } {
2758       set aGuidsMap($aPackage) [OS:genGUID "xcd"]
2759     }
2760
2761     set aSrcFiles [osutils:tk:cxxfiles $xlo mac]
2762     foreach aSrcFile [lsort $aSrcFiles] {
2763       set aFileExt "sourcecode.cpp.cpp"
2764
2765       if { [file extension $aSrcFile] == ".c" } {
2766         set aFileExt "sourcecode.c.c"
2767       } elseif { [file extension $aSrcFile] == ".mm" } {
2768         set aFileExt "sourcecode.cpp.objcpp"
2769       }
2770
2771       if { ! [info exists aGuidsMap($aSrcFile)] } {
2772         set aGuidsMap($aSrcFile) [OS:genGUID "xcd"]
2773       }
2774       set aSrcFileRef "${aSrcFile}_Ref"
2775       if { ! [info exists aGuidsMap($aSrcFileRef)] } {
2776         set aGuidsMap($aSrcFileRef) [OS:genGUID "xcd"]
2777       }
2778       if { ! [info exists written([file tail $aSrcFile])] } {
2779         set written([file tail $aSrcFile]) 1
2780         append aBuildFileSection  "\t\t$aGuidsMap($aSrcFile) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aSrcFileRef) ;\};\n"
2781         append aSrcFileRefSection "\t\t$aGuidsMap($aSrcFileRef) = \{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = ${aFileExt}; name = [wokUtils:FILES:wtail $aSrcFile 1]; path = ../../../[wokUtils:FILES:wtail $aSrcFile 3]; sourceTree = \"<group>\"; \};\n"
2782         append aSrcFileGuids      "\t\t\t\t$aGuidsMap($aSrcFile) ,\n"
2783         append aSrcFileRefGuids   "\t\t\t\t$aGuidsMap($aSrcFileRef) ,\n"
2784       } else {
2785         puts "Warning : more than one occurences for [file tail $aSrcFile]"
2786       }
2787     }
2788
2789     append aGroupSection "\t\t$aGuidsMap($aPackage) = \{\n"
2790     append aGroupSection "\t\t\tisa = PBXGroup;\n"
2791     append aGroupSection "\t\t\tchildren = (\n"
2792     append aGroupSection $aSrcFileRefGuids
2793     append aGroupSection "\t\t\t);\n"
2794     append aGroupSection "\t\t\tname = $xlo;\n"
2795     append aGroupSection "\t\t\tsourceTree = \"<group>\";\n"
2796     append aGroupSection "\t\t\};\n"
2797
2798     # Storing packages IDs for adding them later as a child of toolkit
2799     append aPackagesGuids "\t\t\t\t$aGuidsMap($aPackage) ,\n"
2800   }
2801
2802   # Removing unnecessary newline character from the end.
2803   set aPackagesGuids [string replace $aPackagesGuids end end]
2804
2805   return $aBuildFileSection
2806 }
2807
2808 # Creates folders structure and all necessary files for Xcode project.
2809 proc osutils:xcdtk { theOutDir theToolKit theGuidsMap theIsStatic thePlatform {theTargetType "dylib"} } {
2810   set aPBXBuildPhase "Headers"
2811   set aRunOnlyForDeployment "0"
2812   set aProductType "library.dynamic"
2813   set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = dylib;"
2814   set anExecPrefix "\t\t\t\tEXECUTABLE_PREFIX = lib;"
2815   set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = dylib;"
2816   set aTKDefines [list "OCC_CONVERT_SIGNALS"]
2817   if { $theIsStatic == 1 } {
2818     lappend aTKDefines "OCCT_NO_PLUGINS"
2819   }
2820
2821   if { "$theTargetType" == "executable" } {
2822     set aPBXBuildPhase "CopyFiles"
2823     set aRunOnlyForDeployment "1"
2824     set aProductType "tool"
2825     set anExecExtension ""
2826     set anExecPrefix ""
2827     set aWrapperExtension ""
2828   } elseif { $theIsStatic == 1 } {
2829     set aProductType "library.static"
2830     set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = a;"
2831     set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = a;"
2832   }
2833
2834   set aUsername [exec whoami]
2835
2836   # Creation of folders for Xcode projectP.
2837   set aToolkitDir "${theOutDir}/${theToolKit}.xcodeproj"
2838   wokUtils:FILES:mkdir $aToolkitDir
2839   if { ! [file exists $aToolkitDir] } {
2840     puts stderr "Error: Could not create project directory \"$aToolkitDir\""
2841     return
2842   }
2843
2844   set aUserDataDir "${aToolkitDir}/xcuserdata"
2845   wokUtils:FILES:mkdir $aUserDataDir
2846   if { ! [file exists $aUserDataDir] } {
2847     puts stderr "Error: Could not create xcuserdata directorty in \"$aToolkitDir\""
2848     return
2849   }
2850
2851   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
2852   wokUtils:FILES:mkdir $aUserDataDir
2853   if { ! [file exists $aUserDataDir] } {
2854     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directorty in \"$aToolkitDir\"/xcuserdata"
2855     return
2856   }
2857
2858   set aSchemesDir "${aUserDataDir}/xcschemes"
2859   wokUtils:FILES:mkdir $aSchemesDir
2860   if { ! [file exists $aSchemesDir] } {
2861     puts stderr "Error: Could not create xcschemes directorty in \"$aUserDataDir\""
2862     return
2863   }
2864   # End of folders creation.
2865
2866   # Generating GUID for tookit.
2867   upvar $theGuidsMap aGuidsMap
2868   if { ! [info exists aGuidsMap($theToolKit)] } {
2869     set aGuidsMap($theToolKit) [OS:genGUID "xcd"]
2870   }
2871
2872   # Creating xcscheme file for toolkit from template.
2873   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcd"]
2874   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theToolKit aXcschemeTmpl
2875   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theToolKit) aXcschemeTmpl
2876   set aXcschemeFile [open "$aSchemesDir/${theToolKit}.xcscheme"  "w"]
2877   puts $aXcschemeFile $aXcschemeTmpl
2878   close $aXcschemeFile
2879
2880   # Creating xcschememanagement.plist file for toolkit from template.
2881   set aPlistTmpl [osutils:readtemplate "plist" "xcd"]
2882   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theToolKit aPlistTmpl
2883   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theToolKit) aPlistTmpl
2884   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
2885   puts $aPlistFile $aPlistTmpl
2886   close $aPlistFile
2887
2888   # Creating project.pbxproj file for toolkit.
2889   set aPbxprojFile [open "$aToolkitDir/project.pbxproj" "w"]
2890   puts $aPbxprojFile "// !\$*UTF8*\$!"
2891   puts $aPbxprojFile "\{"
2892   puts $aPbxprojFile "\tarchiveVersion = 1;"
2893   puts $aPbxprojFile "\tclasses = \{"
2894   puts $aPbxprojFile "\t\};"
2895   puts $aPbxprojFile "\tobjectVersion = 46;"
2896   puts $aPbxprojFile "\tobjects = \{\n"
2897
2898   # Begin PBXBuildFile section
2899   set aPackagesGuids ""
2900   set aGroupSection ""
2901   set aSrcFileRefSection ""
2902   set aSrcFileGuids ""
2903   set aDepsFileRefSection ""
2904   set aDepsGuids ""
2905   set aDepsRefGuids ""
2906   set anIncPaths [list "../../../inc"]
2907   set anLibPaths ""
2908
2909   if { [info exists ::env(CSF_OPT_INC)] } {
2910     set anIncCfg [split "$::env(CSF_OPT_INC)" ":"]
2911     foreach anIncCfgPath $anIncCfg {
2912       lappend anIncPaths $anIncCfgPath
2913     }
2914   }
2915   if { [info exists ::env(CSF_OPT_LIB64)] } {
2916     set anLibCfg [split "$::env(CSF_OPT_LIB64)" ":"]
2917     foreach anLibCfgPath $anLibCfg {
2918       lappend anLibPaths $anLibCfgPath
2919     }
2920   }
2921
2922   puts $aPbxprojFile [osutils:xcdtk:sources $theToolKit $theTargetType aSrcFileRefSection aGroupSection aPackagesGuids aSrcFileGuids aGuidsMap anIncPaths]
2923   puts $aPbxprojFile [osutils:xcdtk:deps    $theToolKit $theTargetType aGuidsMap aDepsFileRefSection aDepsGuids aDepsRefGuids $thePlatform $theIsStatic]
2924   # End PBXBuildFile section
2925
2926   # Begin PBXFileReference section
2927   set aToolkitLib "lib${theToolKit}.dylib"
2928   set aPath "$aToolkitLib"
2929   if { "$theTargetType" == "executable" } {
2930     set aPath "$theToolKit"
2931   } elseif { $theIsStatic == 1 } {
2932     set aToolkitLib "lib${theToolKit}.a"
2933   }
2934
2935   if { ! [info exists aGuidsMap($aToolkitLib)] } {
2936     set aGuidsMap($aToolkitLib) [OS:genGUID "xcd"]
2937   }
2938
2939   puts $aPbxprojFile "\t\t$aGuidsMap($aToolkitLib) = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.${theTargetType}\"; includeInIndex = 0; path = $aPath; sourceTree = BUILT_PRODUCTS_DIR; };\n"
2940   puts $aPbxprojFile $aSrcFileRefSection
2941   puts $aPbxprojFile $aDepsFileRefSection
2942   # End PBXFileReference section
2943
2944
2945   # Begin PBXFrameworksBuildPhase section
2946   set aTkFrameworks "${theToolKit}_Frameworks"
2947   if { ! [info exists aGuidsMap($aTkFrameworks)] } {
2948     set aGuidsMap($aTkFrameworks) [OS:genGUID "xcd"]
2949   }
2950
2951   puts $aPbxprojFile "\t\t$aGuidsMap($aTkFrameworks) = \{"
2952   puts $aPbxprojFile "\t\t\tisa = PBXFrameworksBuildPhase;"
2953   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
2954   puts $aPbxprojFile "\t\t\tfiles = ("
2955   puts $aPbxprojFile $aDepsGuids
2956   puts $aPbxprojFile "\t\t\t);"
2957   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
2958   puts $aPbxprojFile "\t\t\};\n"
2959   # End PBXFrameworksBuildPhase section
2960
2961   # Begin PBXGroup section
2962   set aTkPBXGroup "${theToolKit}_PBXGroup"
2963   if { ! [info exists aGuidsMap($aTkPBXGroup)] } {
2964     set aGuidsMap($aTkPBXGroup) [OS:genGUID "xcd"]
2965   }
2966
2967   set aTkSrcGroup "${theToolKit}_SrcGroup"
2968   if { ! [info exists aGuidsMap($aTkSrcGroup)] } {
2969     set aGuidsMap($aTkSrcGroup) [OS:genGUID "xcd"]
2970   }
2971
2972   puts $aPbxprojFile $aGroupSection
2973   puts $aPbxprojFile "\t\t$aGuidsMap($aTkPBXGroup) = \{"
2974   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
2975   puts $aPbxprojFile "\t\t\tchildren = ("
2976   puts $aPbxprojFile $aDepsRefGuids
2977   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSrcGroup) ,"
2978   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aToolkitLib) ,"
2979   puts $aPbxprojFile "\t\t\t);"
2980   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
2981   puts $aPbxprojFile "\t\t\};"
2982   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSrcGroup) = \{"
2983   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
2984   puts $aPbxprojFile "\t\t\tchildren = ("
2985   puts $aPbxprojFile $aPackagesGuids
2986   puts $aPbxprojFile "\t\t\t);"
2987   puts $aPbxprojFile "\t\t\tname = \"Source files\";"
2988   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
2989   puts $aPbxprojFile "\t\t\};\n"
2990   # End PBXGroup section
2991
2992   # Begin PBXHeadersBuildPhase section
2993   set aTkHeaders "${theToolKit}_Headers"
2994   if { ! [info exists aGuidsMap($aTkHeaders)] } {
2995     set aGuidsMap($aTkHeaders) [OS:genGUID "xcd"]
2996   }
2997
2998   puts $aPbxprojFile "\t\t$aGuidsMap($aTkHeaders) = \{"
2999   puts $aPbxprojFile "\t\t\tisa = PBX${aPBXBuildPhase}BuildPhase;"
3000   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3001   puts $aPbxprojFile "\t\t\tfiles = ("
3002   puts $aPbxprojFile "\t\t\t);"
3003   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = ${aRunOnlyForDeployment};"
3004   puts $aPbxprojFile "\t\t\};\n"
3005   # End PBXHeadersBuildPhase section
3006
3007   # Begin PBXNativeTarget section
3008   set aTkBuildCfgListNativeTarget "${theToolKit}_BuildCfgListNativeTarget"
3009   if { ! [info exists aGuidsMap($aTkBuildCfgListNativeTarget)] } {
3010     set aGuidsMap($aTkBuildCfgListNativeTarget) [OS:genGUID "xcd"]
3011   }
3012
3013   set aTkSources "${theToolKit}_Sources"
3014   if { ! [info exists aGuidsMap($aTkSources)] } {
3015     set aGuidsMap($aTkSources) [OS:genGUID "xcd"]
3016   }
3017
3018   puts $aPbxprojFile "\t\t$aGuidsMap($theToolKit) = \{"
3019   puts $aPbxprojFile "\t\t\tisa = PBXNativeTarget;"
3020   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListNativeTarget) ;"
3021   puts $aPbxprojFile "\t\t\tbuildPhases = ("
3022   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSources) ,"
3023   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkFrameworks) ,"
3024   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkHeaders) ,"
3025   puts $aPbxprojFile "\t\t\t);"
3026   puts $aPbxprojFile "\t\t\tbuildRules = ("
3027   puts $aPbxprojFile "\t\t\t);"
3028   puts $aPbxprojFile "\t\t\tdependencies = ("
3029   puts $aPbxprojFile "\t\t\t);"
3030   puts $aPbxprojFile "\t\t\tname = $theToolKit;"
3031   puts $aPbxprojFile "\t\t\tproductName = $theToolKit;"
3032   puts $aPbxprojFile "\t\t\tproductReference = $aGuidsMap($aToolkitLib) ;"
3033   puts $aPbxprojFile "\t\t\tproductType = \"com.apple.product-type.${aProductType}\";"
3034   puts $aPbxprojFile "\t\t\};\n"
3035   # End PBXNativeTarget section
3036
3037   # Begin PBXProject section
3038   set aTkProjectObj "${theToolKit}_ProjectObj"
3039   if { ! [info exists aGuidsMap($aTkProjectObj)] } {
3040     set aGuidsMap($aTkProjectObj) [OS:genGUID "xcd"]
3041   }
3042
3043   set aTkBuildCfgListProj "${theToolKit}_BuildCfgListProj"
3044   if { ! [info exists aGuidsMap($aTkBuildCfgListProj)] } {
3045     set aGuidsMap($aTkBuildCfgListProj) [OS:genGUID "xcd"]
3046   }
3047
3048   puts $aPbxprojFile "\t\t$aGuidsMap($aTkProjectObj) = \{"
3049   puts $aPbxprojFile "\t\t\tisa = PBXProject;"
3050   puts $aPbxprojFile "\t\t\tattributes = \{"
3051   puts $aPbxprojFile "\t\t\t\tLastUpgradeCheck = 0430;"
3052   puts $aPbxprojFile "\t\t\t\};"
3053   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListProj) ;"
3054   puts $aPbxprojFile "\t\t\tcompatibilityVersion = \"Xcode 3.2\";"
3055   puts $aPbxprojFile "\t\t\tdevelopmentRegion = English;"
3056   puts $aPbxprojFile "\t\t\thasScannedForEncodings = 0;"
3057   puts $aPbxprojFile "\t\t\tknownRegions = ("
3058   puts $aPbxprojFile "\t\t\t\ten,"
3059   puts $aPbxprojFile "\t\t\t);"
3060   puts $aPbxprojFile "\t\t\tmainGroup = $aGuidsMap($aTkPBXGroup);"
3061   puts $aPbxprojFile "\t\t\tproductRefGroup = $aGuidsMap($aTkPBXGroup);"
3062   puts $aPbxprojFile "\t\t\tprojectDirPath = \"\";"
3063   puts $aPbxprojFile "\t\t\tprojectRoot = \"\";"
3064   puts $aPbxprojFile "\t\t\ttargets = ("
3065   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($theToolKit) ,"
3066   puts $aPbxprojFile "\t\t\t);"
3067   puts $aPbxprojFile "\t\t\};\n"
3068   # End PBXProject section
3069
3070   # Begin PBXSourcesBuildPhase section
3071   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSources) = \{"
3072   puts $aPbxprojFile "\t\t\tisa = PBXSourcesBuildPhase;"
3073   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3074   puts $aPbxprojFile "\t\t\tfiles = ("
3075   puts $aPbxprojFile $aSrcFileGuids
3076   puts $aPbxprojFile "\t\t\t);"
3077   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
3078   puts $aPbxprojFile "\t\t\};\n"
3079   # End PBXSourcesBuildPhase section
3080
3081   # Begin XCBuildConfiguration section
3082   set aTkDebugProject "${theToolKit}_DebugProject"
3083   if { ! [info exists aGuidsMap($aTkDebugProject)] } {
3084     set aGuidsMap($aTkDebugProject) [OS:genGUID "xcd"]
3085   }
3086
3087   set aTkReleaseProject "${theToolKit}_ReleaseProject"
3088   if { ! [info exists aGuidsMap($aTkReleaseProject)] } {
3089     set aGuidsMap($aTkReleaseProject) [OS:genGUID "xcd"]
3090   }
3091
3092   set aTkDebugNativeTarget "${theToolKit}_DebugNativeTarget"
3093   if { ! [info exists aGuidsMap($aTkDebugNativeTarget)] } {
3094     set aGuidsMap($aTkDebugNativeTarget) [OS:genGUID "xcd"]
3095   }
3096
3097   set aTkReleaseNativeTarget "${theToolKit}_ReleaseNativeTarget"
3098   if { ! [info exists aGuidsMap($aTkReleaseNativeTarget)] } {
3099     set aGuidsMap($aTkReleaseNativeTarget) [OS:genGUID "xcd"]
3100   }
3101
3102   # Debug target
3103   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugProject) = \{"
3104   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3105   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3106
3107   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;"
3108   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3109   if { "$thePlatform" == "ios" } {
3110     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3111     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3112     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3113     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3114   }
3115   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3116   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3117   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3118   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = NO;"
3119   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3120   puts $aPbxprojFile "\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;"
3121   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3122   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;"
3123   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3124   puts $aPbxprojFile "\t\t\t\t\t\"DEBUG=1\","
3125   puts $aPbxprojFile "\t\t\t\t\t\"\$\(inherited\)\","
3126   puts $aPbxprojFile "\t\t\t\t);"
3127   puts $aPbxprojFile "\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;"
3128   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3129   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3130   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3131   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3132   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3133   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64D)\"; "
3134   if { "$thePlatform" == "ios" } {
3135     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = NO;"
3136     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3137   } else {
3138     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = YES;"
3139   }
3140   puts $aPbxprojFile "\t\t\t\};"
3141
3142   puts $aPbxprojFile "\t\t\tname = Debug;"
3143   puts $aPbxprojFile "\t\t\};"
3144
3145   # Release target
3146   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseProject) = \{"
3147   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3148   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3149
3150   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";"
3151   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3152   if { "$thePlatform" == "ios" } {
3153     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3154     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3155     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3156     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3157   }
3158   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3159   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3160   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3161   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = YES;"
3162   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3163   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3164   puts $aPbxprojFile "\t\t\t\tDEAD_CODE_STRIPPING = NO;"
3165   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 2;"
3166   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3167   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3168   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3169   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3170   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3171   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64)\";"
3172   if { "$thePlatform" == "ios" } {
3173     puts $aPbxprojFile "\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;"
3174     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3175   }
3176   puts $aPbxprojFile "\t\t\t\};"
3177   puts $aPbxprojFile "\t\t\tname = Release;"
3178   puts $aPbxprojFile "\t\t\};"
3179   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugNativeTarget) = \{"
3180   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3181   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3182   puts $aPbxprojFile "${anExecExtension}"
3183   puts $aPbxprojFile "${anExecPrefix}"
3184   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3185   foreach aMacro $aTKDefines {
3186     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3187   }
3188   puts $aPbxprojFile "\t\t\t\t);"
3189
3190   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3191   foreach anIncPath $anIncPaths {
3192     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3193   }
3194   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3195   puts $aPbxprojFile "\t\t\t\t);"
3196
3197   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3198   foreach anLibPath $anLibPaths {
3199     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3200   }
3201   puts $aPbxprojFile "\t\t\t\t);"
3202
3203   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3204   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3205   puts $aPbxprojFile "\t\t\t\t);"
3206   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3207   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3208   puts $aPbxprojFile "\t\t\t\t);"
3209   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3210   set anUserHeaderSearchPath "\t\t\t\tUSER_HEADER_SEARCH_PATHS = \""
3211   foreach anIncPath $anIncPaths {
3212     append anUserHeaderSearchPath " ${anIncPath}"
3213   }
3214   append anUserHeaderSearchPath "\";"
3215   puts $aPbxprojFile $anUserHeaderSearchPath
3216   puts $aPbxprojFile "${aWrapperExtension}"
3217   puts $aPbxprojFile "\t\t\t\};"
3218   puts $aPbxprojFile "\t\t\tname = Debug;"
3219   puts $aPbxprojFile "\t\t\};"
3220   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseNativeTarget) = \{"
3221   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3222   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3223   puts $aPbxprojFile "${anExecExtension}"
3224   puts $aPbxprojFile "${anExecPrefix}"
3225   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3226   foreach aMacro $aTKDefines {
3227     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3228   }
3229   puts $aPbxprojFile "\t\t\t\t);"
3230   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3231   foreach anIncPath $anIncPaths {
3232     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3233   }
3234   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3235   puts $aPbxprojFile "\t\t\t\t);"
3236
3237   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3238   foreach anLibPath $anLibPaths {
3239     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3240   }
3241   puts $aPbxprojFile "\t\t\t\t);"
3242
3243   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3244   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3245   puts $aPbxprojFile "\t\t\t\t);"
3246   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3247   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3248   puts $aPbxprojFile "\t\t\t\t);"
3249   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3250   puts $aPbxprojFile $anUserHeaderSearchPath
3251   puts $aPbxprojFile "${aWrapperExtension}"
3252   puts $aPbxprojFile "\t\t\t\};"
3253   puts $aPbxprojFile "\t\t\tname = Release;"
3254   puts $aPbxprojFile "\t\t\};\n"
3255   # End XCBuildConfiguration section
3256
3257   # Begin XCConfigurationList section
3258   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListProj) = \{"
3259   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3260   puts $aPbxprojFile "\t\tbuildConfigurations = ("
3261   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugProject) ,"
3262   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseProject) ,"
3263   puts $aPbxprojFile "\t\t\t);"
3264   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3265   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3266   puts $aPbxprojFile "\t\t\};"
3267   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListNativeTarget) = \{"
3268   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3269   puts $aPbxprojFile "\t\t\tbuildConfigurations = ("
3270   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugNativeTarget) ,"
3271   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseNativeTarget) ,"
3272   puts $aPbxprojFile "\t\t\t);"
3273   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3274   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3275   puts $aPbxprojFile "\t\t\};\n"
3276   # End XCConfigurationList section
3277
3278   puts $aPbxprojFile "\t\};"
3279   puts $aPbxprojFile "\trootObject = $aGuidsMap($aTkProjectObj) ;"
3280   puts $aPbxprojFile "\}"
3281
3282   close $aPbxprojFile
3283 }
3284
3285 proc osutils:xcdx { theOutDir theExecutable theGuidsMap } {
3286   set aUsername [exec whoami]
3287
3288   # Creating folders for Xcode project file.
3289   set anExecutableDir "${theOutDir}/${theExecutable}.xcodeproj"
3290   wokUtils:FILES:mkdir $anExecutableDir
3291   if { ! [file exists $anExecutableDir] } {
3292     puts stderr "Error: Could not create project directory \"$anExecutableDir\""
3293     return
3294   }
3295
3296   set aUserDataDir "${anExecutableDir}/xcuserdata"
3297   wokUtils:FILES:mkdir $aUserDataDir
3298   if { ! [file exists $aUserDataDir] } {
3299     puts stderr "Error: Could not create xcuserdata directorty in \"$anExecutableDir\""
3300     return
3301   }
3302
3303   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
3304   wokUtils:FILES:mkdir $aUserDataDir
3305   if { ! [file exists $aUserDataDir] } {
3306     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directorty in \"$anExecutableDir\"/xcuserdata"
3307     return
3308   }
3309
3310   set aSchemesDir "${aUserDataDir}/xcschemes"
3311   wokUtils:FILES:mkdir $aSchemesDir
3312   if { ! [file exists $aSchemesDir] } {
3313     puts stderr "Error: Could not create xcschemes directorty in \"$aUserDataDir\""
3314     return
3315   }
3316   # End folders creation.
3317
3318   # Generating GUID for tookit.
3319   upvar $theGuidsMap aGuidsMap
3320   if { ! [info exists aGuidsMap($theExecutable)] } {
3321     set aGuidsMap($theExecutable) [OS:genGUID "xcd"]
3322   }
3323
3324   # Creating xcscheme file for toolkit from template.
3325   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcode"]
3326   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theExecutable aXcschemeTmpl
3327   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theExecutable) aXcschemeTmpl
3328   set aXcschemeFile [open "$aSchemesDir/${theExecutable}.xcscheme"  "w"]
3329   puts $aXcschemeFile $aXcschemeTmpl
3330   close $aXcschemeFile
3331
3332   # Creating xcschememanagement.plist file for toolkit from template.
3333   set aPlistTmpl [osutils:readtemplate "plist" "xcode"]
3334   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theExecutable aPlistTmpl
3335   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theExecutable) aPlistTmpl
3336   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
3337   puts $aPlistFile $aPlistTmpl
3338   close $aPlistFile
3339 }
3340
3341 # Returns available Windows SDKs versions
3342 proc osutils:sdk { theSdkMajorVer {isQuietMode false} {theSdkDirectories {}} } {
3343   if { ![llength ${theSdkDirectories}] } {
3344     foreach anEnvVar { "ProgramFiles" "ProgramFiles\(x86\)" "ProgramW6432" } {
3345       if {[ info exists ::env(${anEnvVar}) ]} {
3346         lappend theSdkDirectories "$::env(${anEnvVar})/Windows Kits/${theSdkMajorVer}/Include"
3347       }
3348     }
3349   }
3350
3351   set sdk_versions {}
3352   foreach sdk_dir ${theSdkDirectories} {
3353     if { [file isdirectory ${sdk_dir}] } {
3354       lappend sdk_versions [glob -tails -directory "${sdk_dir}" -type d *]
3355     }
3356   }
3357
3358   if {![llength ${sdk_versions}] && !${isQuietMode}} {
3359     error "Error : Could not find Windows SDK ${theSdkMajorVer}"
3360   }
3361
3362   return [join [lsort -unique ${sdk_versions}] " "]
3363 }
3364
3365 # Generate global properties to Visual Studio project file for UWP solution
3366 proc osutils:uwp:proj { isUWP theProjTmpl } {
3367
3368   set uwp_properties ""
3369   set uwp_generate_metadata ""
3370   set uwp_app_container ""
3371
3372   set format_template ""
3373
3374   if { $isUWP } {
3375     set sdk_versions [osutils:sdk 10]
3376     set sdk_max_ver [lindex ${sdk_versions} end]
3377
3378     set uwp_properties "<DefaultLanguage>en-US</DefaultLanguage>\n   \
3379 <ApplicationType>Windows Store</ApplicationType>\n   \
3380 <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\n   \
3381 <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\n   \
3382 <AppContainerApplication>true</AppContainerApplication>\n   \
3383 <WindowsTargetPlatformVersion>${sdk_max_ver}</WindowsTargetPlatformVersion>\n   \
3384 <WindowsTargetPlatformMinVersion>${sdk_max_ver}</WindowsTargetPlatformMinVersion>"
3385
3386     set uwp_generate_metadata        "<GenerateWindowsMetadata>false</GenerateWindowsMetadata>"
3387
3388     regsub -all -- {[\r\n\s]*<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>} ${theProjTmpl} "" theProjTmpl
3389   } else {
3390     set format_template "\[\\r\\n\\s\]*"
3391   }
3392
3393   regsub -all -- "${format_template}__UWP_PROPERTIES__"        ${theProjTmpl} "${uwp_properties}" theProjTmpl
3394   regsub -all -- "${format_template}__UWP_GENERATE_METADATA__" ${theProjTmpl} "${uwp_generate_metadata}" theProjTmpl
3395
3396   return ${theProjTmpl}
3397 }
3398
3399 # Report all files found in package directory but not listed in FILES
3400 proc osutils:checksrcfiles { theUnit } {
3401   global path
3402   set aCasRoot [file normalize ${path}]
3403
3404   if {![file isdirectory ${aCasRoot}]} {
3405     puts "OCCT directory is not defined correctly: ${aCasRoot}"
3406     return
3407   }
3408
3409   set anUnitAbsPath [file normalize "${aCasRoot}/src/${theUnit}"]
3410
3411   if {[file exists "${anUnitAbsPath}/FILES"]} {
3412     set aFilesFile [open "${anUnitAbsPath}/FILES" rb]
3413     set aFilesFileList [split [read ${aFilesFile}] "\n"]
3414     close ${aFilesFile}
3415
3416     set aFilesFileList [lsearch -inline -all -not -exact ${aFilesFileList} ""]
3417
3418     # report all files not listed in FILES
3419     set anAllFiles [glob -tails -nocomplain -dir ${anUnitAbsPath} "*"]
3420     foreach aFile ${anAllFiles} {
3421       if { "${aFile}" == "FILES" } {
3422         continue
3423       }
3424       if { [lsearch -exact ${aFilesFileList} ${aFile}] == -1 } {
3425         puts "Warning: file ${anUnitAbsPath}/${aFile} is not listed in ${anUnitAbsPath}/FILES!"
3426       }
3427     }
3428   }
3429 }