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