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