0030966: Configuration, genproj.tcl - look for an optional libraries e57 and xerces
[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   if { "$::HAVE_E57" == "true" && "$theOS" != "wnt" } {
1374     # exclude wnt, as there are different pragma lib depending on debug/release
1375     set aLibsMap(CSF_E57)    "E57RefImpl"
1376     set aLibsMap(CSF_xerces) "xerces-c"
1377   }
1378
1379   if { "$theOS" == "wnt" } {
1380     #  WinAPI libraries
1381     set aLibsMap(CSF_kernel32)     "kernel32"
1382     set aLibsMap(CSF_advapi32)     "advapi32"
1383     set aLibsMap(CSF_gdi32)        "gdi32"
1384     set aLibsMap(CSF_user32)       "user32 comdlg32"
1385     set aLibsMap(CSF_shell32)      "shell32"
1386     set aLibsMap(CSF_opengl32)     "opengl32"
1387     set aLibsMap(CSF_wsock32)      "wsock32"
1388     set aLibsMap(CSF_netapi32)     "netapi32"
1389     set aLibsMap(CSF_winmm)        "winmm"
1390     set aLibsMap(CSF_OpenGlLibs)   "opengl32"
1391     if { "$::HAVE_GLES2" == "true" } {
1392       set aLibsMap(CSF_OpenGlLibs) "libEGL libGLESv2"
1393     }
1394     set aLibsMap(CSF_psapi)        "Psapi"
1395     set aLibsMap(CSF_d3d9)         "d3d9"
1396
1397     # the naming is different on Windows
1398     set aLibsMap(CSF_TclLibs)      "tcl86"
1399     set aLibsMap(CSF_TclTkLibs)    "tk86"
1400
1401     set aLibsMap(CSF_QT)           "QtCore4 QtGui4"
1402
1403     # tbb headers define different pragma lib depending on debug/release
1404     set aLibsMap(CSF_TBB) ""
1405   } else {
1406     set aLibsMap(CSF_dl)           "dl"
1407     if { "$theOS" == "mac" || "$theOS" == "ios" } {
1408       set aLibsMap(CSF_objc)       "objc"
1409       if { "$theOS" == "ios" } {
1410         set aFrmsMap(CSF_Appkit)     "UIKit"
1411         set aFrmsMap(CSF_OpenGlLibs) "OpenGLES"
1412       } else {
1413         set aFrmsMap(CSF_Appkit)     "AppKit"
1414         set aFrmsMap(CSF_OpenGlLibs) "OpenGL"
1415       }
1416       set aFrmsMap(CSF_IOKit)      "IOKit"
1417       set aFrmsMap(CSF_TclLibs)    "Tcl"
1418       set aLibsMap(CSF_TclLibs)    ""
1419       set aFrmsMap(CSF_TclTkLibs)  "Tk"
1420       set aLibsMap(CSF_TclTkLibs)  ""
1421       set aLibsMap(CSF_QT)         "QtCore QtGui"
1422     } else {
1423       set aLibsMap(CSF_fontconfig) "fontconfig"
1424       if { "$theOS" == "qnx" } {
1425         # CSF_ThreadLibs - pthread API is part of libc on QNX
1426         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1427       } else {
1428         set aLibsMap(CSF_ThreadLibs) "pthread rt"
1429         set aLibsMap(CSF_OpenGlLibs) "GL"
1430         set aLibsMap(CSF_TclTkLibs)  "X11 tk8.6"
1431         set aLibsMap(CSF_XwLibs)     "X11 Xext Xmu Xi"
1432         set aLibsMap(CSF_MotifLibs)  "X11"
1433       }
1434
1435       if { "$::HAVE_GLES2" == "true" } {
1436         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1437       }
1438     }
1439   }
1440 }
1441
1442 # Returns string of library dependencies for generation of Visual Studio project or make lists.
1443 proc osutils:vtkCsf {{theOS ""}} {
1444   set aVtkVer "6.1"
1445
1446   set aPathSplitter ":"
1447   if {"$theOS" == "wnt"} {
1448     set aPathSplitter ";"
1449   }
1450
1451   set anOptIncs [split $::env(CSF_OPT_INC) "$aPathSplitter"]
1452   foreach anIncItem $anOptIncs {
1453     if {[regexp -- "vtk-(.*)$" [file tail $anIncItem] dummy aFoundVtkVer]} {
1454       set aVtkVer $aFoundVtkVer
1455     }
1456   }
1457
1458   set aLibArray [list vtkCommonCore vtkCommonDataModel vtkCommonExecutionModel vtkCommonMath vtkCommonTransforms vtkRenderingCore \
1459                       vtkRenderingOpenGL  vtkFiltersGeneral vtkIOCore vtkIOImage vtkImagingCore vtkInteractionStyle]
1460
1461   # Additional suffices for the libraries
1462   set anIdx 0
1463   foreach anItem $aLibArray {
1464     lset aLibArray $anIdx $anItem-$aVtkVer
1465     incr anIdx
1466   }
1467
1468   return [join $aLibArray " "]
1469 }
1470
1471 # @param theLibsList   - dependencies (libraries  list)
1472 # @param theFrameworks - dependencies (frameworks list, OS X specific)
1473 proc osutils:usedOsLibs { theToolKit theOS theLibsList theFrameworks } {
1474   global path
1475   upvar $theLibsList   aLibsList
1476   upvar $theFrameworks aFrameworks
1477   set aLibsList   [list]
1478   set aFrameworks [list]
1479
1480   osutils:csfList $theOS aLibsMap aFrmsMap
1481
1482   foreach aCsfElem [osutils:tk:csfInExternlib "$path/src/${theToolKit}/EXTERNLIB"] {
1483     if [info exists aLibsMap($aCsfElem)] {
1484       foreach aLib [split "$aLibsMap($aCsfElem)"] {
1485         if { [lsearch $aLibsList $aLib] == "-1" } {
1486           lappend aLibsList $aLib
1487         }
1488       }
1489     }
1490     if [info exists aFrmsMap($aCsfElem)] {
1491       foreach aFrm [split "$aFrmsMap($aCsfElem)"] {
1492         if { [lsearch $aFrameworks $aFrm] == "-1" } {
1493           lappend aFrameworks $aFrm
1494         }
1495       }
1496     }
1497   }
1498 }
1499
1500 # Returns liste of UD in a toolkit. tkloc is a full path wok.
1501 proc osutils:tk:units { tkloc } {
1502   global path
1503   set l {}
1504   set PACKAGES "$path/src/$tkloc/PACKAGES"
1505   foreach u [wokUtils:FILES:FileToList $PACKAGES] {
1506     if {[file isdirectory "$path/src/$u"]} {
1507       lappend l $u
1508     }
1509   }
1510   if { $l == {} } {
1511     ;#puts stderr "Warning. No devunit included in $tkloc"
1512   }
1513   return $l
1514 }
1515
1516 proc osutils:justwnt { listloc } {
1517   set goaway [list Xw]
1518   return [osutils:juststation $goaway $listloc]
1519 }
1520
1521 # remove from listloc OpenCascade units indesirables on NT
1522 proc osutils:juststation {goaway listloc} {
1523   global path
1524   set lret {}
1525   foreach u $listloc {
1526     if {([file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 )
1527      || (![file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 ) } {
1528       lappend lret $u
1529     }
1530   }
1531   return $lret
1532 }
1533
1534 # intersect3 - perform the intersecting of two lists, returning a list containing three lists.
1535 # The first list is everything in the first list that wasn't in the second,
1536 # the second list contains the intersection of the two lists, the third list contains everything
1537 # in the second list that wasn't in the first.
1538 proc osutils:intersect3 {list1 list2} {
1539   set la1(0) {} ; unset la1(0)
1540   set lai(0) {} ; unset lai(0)
1541   set la2(0) {} ; unset la2(0)
1542   foreach v $list1 {
1543     set la1($v) {}
1544   }
1545   foreach v $list2 {
1546     set la2($v) {}
1547   }
1548   foreach elem [concat $list1 $list2] {
1549     if {[info exists la1($elem)] && [info exists la2($elem)]} {
1550       unset la1($elem)
1551       unset la2($elem)
1552       set lai($elem) {}
1553     }
1554   }
1555   list [lsort [array names la1]] [lsort [array names lai]] [lsort [array names la2]]
1556 }
1557
1558 # Prepare relative path
1559 proc relativePath {thePathFrom thePathTo} {
1560   if { [file isdirectory "$thePathFrom"] == 0 } {
1561     return ""
1562   }
1563
1564   set aPathFrom [file normalize "$thePathFrom"]
1565   set aPathTo   [file normalize "$thePathTo"]
1566
1567   set aCutedPathFrom "${aPathFrom}/dummy"
1568   set aRelatedDeepPath ""
1569
1570   while { "$aCutedPathFrom" != [file normalize "$aCutedPathFrom/.."] } {
1571     set aCutedPathFrom [file normalize "$aCutedPathFrom/.."]
1572     # does aPathTo contain aCutedPathFrom?
1573     regsub -all $aCutedPathFrom $aPathTo "" aPathFromAfterCut
1574     if { "$aPathFromAfterCut" != "$aPathTo" } { # if so
1575       if { "$aCutedPathFrom" == "$aPathFrom" } { # just go higher, for example, ./somefolder/someotherfolder
1576         set aPathTo ".${aPathTo}"
1577       } elseif { "$aCutedPathFrom" == "$aPathTo" } { # remove the last "/"
1578         set aRelatedDeepPath [string replace $aRelatedDeepPath end end ""]
1579       }
1580       regsub -all $aCutedPathFrom $aPathTo $aRelatedDeepPath aPathToAfterCut
1581       regsub -all "//" $aPathToAfterCut "/" aPathToAfterCut
1582       return $aPathToAfterCut
1583     }
1584     set aRelatedDeepPath "$aRelatedDeepPath../"
1585
1586   }
1587
1588   return $thePathTo
1589 }
1590
1591 proc wokUtils:EASY:bs1 { s } {
1592     regsub -all {/} $s {\\} r
1593     return $r
1594 }
1595
1596 # Returs for a full path the liste of n last directory part
1597 # n = 1 => tail
1598 # n = 2 => dir/file.c
1599 # n = 3 => sdir/dir/file.c
1600 # etc..
1601 proc wokUtils:FILES:wtail { f n } {
1602     set ll [expr [llength [set lif [file split $f]]] -$n]
1603     return [join [lrange $lif $ll end] /]
1604 }
1605
1606 # Generate entry for one source file in Visual Studio 10 project file
1607 proc osutils:vcxproj:cxxfile { theFile theParams } {
1608   if { $theParams == "" } {
1609     return "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\" />\n"
1610   }
1611
1612   set aParams [string trim ${theParams}]
1613   append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
1614   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1615   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1616   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1617   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1618   append text "    </ClCompile>\n"
1619   return $text
1620 }
1621
1622 # Generate entry for one header file in Visual Studio 10 project file
1623 proc osutils:vcxproj:hxxfile { theFile } { return "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\" />\n" }
1624
1625 # Generate Visual Studio 2010 project filters file
1626 proc osutils:vcxproj:filters { dir proj theCxxFilesMap theHxxFilesMap } {
1627   upvar $theCxxFilesMap aCxxFilesMap
1628   upvar $theHxxFilesMap aHxxFilesMap
1629
1630   # header
1631   append text "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
1632   append text "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
1633
1634   # list of "filters" (units)
1635   append text "  <ItemGroup>\n"
1636   append text "    <Filter Include=\"Source files\">\n"
1637   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1638   append text "    </Filter>\n"
1639   append text "    <Filter Include=\"Header files\">\n"
1640   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1641   append text "    </Filter>\n"
1642   foreach unit $aCxxFilesMap(units) {
1643     append text "    <Filter Include=\"Source files\\${unit}\">\n"
1644     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1645     append text "    </Filter>\n"
1646   }
1647   foreach unit $aHxxFilesMap(units) {
1648     append text "    <Filter Include=\"Header files\\${unit}\">\n"
1649     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1650     append text "    </Filter>\n"
1651   }
1652   append text "  </ItemGroup>\n"
1653
1654   # list of cxx files
1655   append text "  <ItemGroup>\n"
1656   foreach unit $aCxxFilesMap(units) {
1657     foreach file $aCxxFilesMap($unit) {
1658       append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1659       append text "      <Filter>Source files\\${unit}</Filter>\n"
1660       append text "    </ClCompile>\n"
1661     }
1662   }
1663   append text "  </ItemGroup>\n"
1664
1665   # list of hxx files
1666   append text "  <ItemGroup>\n"
1667   foreach unit $aHxxFilesMap(units) {
1668     foreach file $aHxxFilesMap($unit) {
1669       append text "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1670       append text "      <Filter>Header files\\${unit}</Filter>\n"
1671       append text "    </ClInclude>\n"
1672     }
1673   }
1674   append text "  </ItemGroup>\n"
1675
1676   append text "  <ItemGroup>\n"
1677   append text "    <ResourceCompile Include=\"${proj}.rc\" />\n"
1678   append text "  </ItemGroup>\n"
1679
1680   # end
1681   append text "</Project>"
1682
1683   # write file
1684   set fp [open [set fvcproj [file join $dir ${proj}.vcxproj.filters]] w]
1685   fconfigure $fp -translation crlf
1686   puts $fp $text
1687   close $fp
1688
1689   return ${proj}.vcxproj.filters
1690 }
1691
1692 # Generate RC file content for ToolKit from template
1693 proc osutils:readtemplate:rc {theOutDir theToolKit} {
1694   set aLoc "$::THE_CASROOT/adm/templates/template_dll.rc"
1695   set aBody [wokUtils:FILES:FileToString $aLoc]
1696   regsub -all -- {__TKNAM__} $aBody $theToolKit aBody
1697
1698   set aFile [open "${theOutDir}/${theToolKit}.rc" "w"]
1699   fconfigure $aFile -translation lf
1700   puts $aFile $aBody
1701   close $aFile
1702   return "${theOutDir}/${theToolKit}.rc"
1703 }
1704
1705 # Generate Visual Studio project file for ToolKit
1706 proc osutils:vcproj { theVcVer isUWP theOutDir theToolKit theGuidsMap } {
1707   set theProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 0]
1708
1709   set l_compilable [osutils:compilable wnt]
1710   regsub -all -- {__TKNAM__} $theProjTmpl $theToolKit theProjTmpl
1711
1712   upvar $theGuidsMap aGuidsMap
1713   if { ! [info exists aGuidsMap($theToolKit)] } {
1714     set aGuidsMap($theToolKit) [OS:genGUID]
1715   }
1716   regsub -all -- {__PROJECT_GUID__} $theProjTmpl $aGuidsMap($theToolKit) theProjTmpl
1717
1718   set theProjTmpl [osutils:uwp:proj $isUWP ${theProjTmpl}]
1719
1720   set aUsedLibs [list]
1721
1722   if { $isUWP } {
1723     lappend aUsedLibs "WindowsApp.lib"
1724   }
1725
1726   foreach tkx [osutils:commonUsedTK  $theToolKit] {
1727     lappend aUsedLibs "${tkx}.lib"
1728   }
1729
1730   osutils:usedOsLibs $theToolKit "wnt" aLibs aFrameworks
1731   foreach aLibIter $aLibs {
1732     lappend aUsedLibs "${aLibIter}.lib"
1733   }
1734
1735   # correct names of referred third-party libraries that are named with suffix
1736   # depending on VC version
1737   set aVCRTVer [string range $theVcVer 0 3]
1738   regsub -all -- {vc[0-9]+} $aUsedLibs $aVCRTVer aUsedLibs
1739
1740   # and put this list to project file
1741   #puts "$theToolKit requires  $aUsedLibs"
1742   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1743     set aUsedLibs [join $aUsedLibs {;}]
1744   }
1745   regsub -all -- {__TKDEP__} $theProjTmpl $aUsedLibs theProjTmpl
1746
1747   set anIncPaths "..\\..\\..\\inc"
1748 #  set aTKDefines ""
1749   set aFilesSection ""
1750   set aVcFilesCxx(units) ""
1751   set aVcFilesHxx(units) ""
1752   set listloc [osutils:tk:units $theToolKit]
1753   if [array exists written] { unset written }
1754   #puts "\t1 [wokparam -v %CMPLRS_CXX_Options [w_info -f]] father"
1755   #puts "\t2 [wokparam -v %CMPLRS_CXX_Options] branch"
1756   #puts "\t1 [wokparam -v %CMPLRS_C_Options [w_info -f]] father"
1757   #puts "\t2 [wokparam -v %CMPLRS_C_Options] branch"
1758   set fxloparamfcxx [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx f] [_get_options wnt cmplrs_cxx b]] 2]
1759   set fxloparamfc   [lindex [osutils:intersect3 [_get_options wnt cmplrs_c f] [_get_options wnt cmplrs_c b]] 2]
1760   set fxloparam ""
1761   foreach fxlo $listloc {
1762     set xlo $fxlo
1763     set aSrcFiles [osutils:tk:cxxfiles $xlo wnt]
1764         set aHxxFiles [osutils:tk:hxxfiles $xlo wnt]
1765         set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx $fxlo]
1766     if {$fxlo_cmplrs_options_cxx == ""} {
1767       set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx b]
1768     }
1769         set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c $fxlo]
1770     if {$fxlo_cmplrs_options_c == ""} {
1771       set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c b]
1772     }
1773     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx b] $fxlo_cmplrs_options_cxx] 2]"
1774     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_c b] $fxlo_cmplrs_options_c] 2]"
1775         #puts "\t3 [wokparam -v %CMPLRS_CXX_Options] branch CXX "
1776         #puts "\t4 [wokparam -v %CMPLRS_CXX_Options $fxlo] $fxlo  CXX"
1777         #puts "\t5 [wokparam -v %CMPLRS_C_Options] branch C"
1778         #puts "\t6 [wokparam -v %CMPLRS_C_Options   $fxlo] $fxlo  C"
1779     set needparam ""
1780     foreach partopt $fxloparam {
1781       if {[string first "-I" $partopt] == "0"} {
1782         # this is an additional includes search path
1783         continue
1784       }
1785       set needparam "$needparam $partopt"
1786     }
1787
1788     # Format of projects in vc10+ is different from vc7-9
1789     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1790       foreach aSrcFile [lsort $aSrcFiles] {
1791         if { ![info exists written([file tail $aSrcFile])] } {
1792           set written([file tail $aSrcFile]) 1
1793           append aFilesSection [osutils:vcxproj:cxxfile $aSrcFile $needparam]
1794         } else {
1795           puts "Warning : in vcproj more than one occurences for [file tail $aSrcFile]"
1796         }
1797         if { ! [info exists aVcFilesCxx($xlo)] } { lappend aVcFilesCxx(units) $xlo }
1798         lappend aVcFilesCxx($xlo) $aSrcFile
1799       }
1800       foreach aHxxFile [lsort $aHxxFiles] {
1801         if { ![info exists written([file tail $aHxxFile])] } {
1802           set written([file tail $aHxxFile]) 1
1803           append aFilesSection [osutils:vcxproj:hxxfile $aHxxFile]
1804         } else {
1805           puts "Warning : in vcproj more than one occurences for [file tail $aHxxFile]"
1806         }
1807         if { ! [info exists aVcFilesHxx($xlo)] } { lappend aVcFilesHxx(units) $xlo }
1808         lappend aVcFilesHxx($xlo) $aHxxFile
1809       }
1810     } else {
1811       append aFilesSection "\t\t\t<Filter\n"
1812       append aFilesSection "\t\t\t\tName=\"${xlo}\"\n"
1813       append aFilesSection "\t\t\t\t>\n"
1814       foreach aSrcFile [lsort $aSrcFiles] {
1815         if { ![info exists written([file tail $aSrcFile])] } {
1816           set written([file tail $aSrcFile]) 1
1817           append aFilesSection [osutils:vcproj:file $theVcVer $aSrcFile $needparam]
1818         } else {
1819           puts "Warning : in vcproj more than one occurences for [file tail $aSrcFile]"
1820         }
1821       }
1822       append aFilesSection "\t\t\t</Filter>\n"
1823     }
1824   }
1825
1826   regsub -all -- {__TKINC__}  $theProjTmpl $anIncPaths theProjTmpl
1827   regsub -all -- {__FILES__}  $theProjTmpl $aFilesSection theProjTmpl
1828
1829   # write file
1830   set aFile [open [set aVcFiles [file join $theOutDir ${theToolKit}.[osutils:vcproj:ext $theVcVer]]] w]
1831   fconfigure $aFile -translation crlf
1832   puts $aFile $theProjTmpl
1833   close $aFile
1834
1835   # write filters file for vc10+
1836   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1837     lappend aVcFiles [osutils:vcxproj:filters $theOutDir $theToolKit aVcFilesCxx aVcFilesHxx]
1838   }
1839
1840   # write resource file
1841   lappend aVcFiles [osutils:readtemplate:rc $theOutDir $theToolKit]
1842
1843   return $aVcFiles
1844 }
1845
1846 # for a unit returns a map containing all its file in the current
1847 # workbench
1848 # local = 1 only local files
1849 proc osutils:tk:loadunit { loc map } {
1850   #puts $loc
1851   upvar $map TLOC
1852   catch { unset TLOC }
1853   set lfiles [_get_used_files $loc]
1854   foreach f $lfiles {
1855     #puts "\t$f"
1856     set t [lindex $f 0]
1857     set p [lindex $f 2]
1858     if [info exists TLOC($t)] {
1859       set l $TLOC($t)
1860       lappend l $p
1861       set TLOC($t) $l
1862     } else {
1863       set TLOC($t) $p
1864     }
1865   }
1866   return
1867 }
1868
1869 # Returns the list of all files name in a toolkit within specified list of file extensions.
1870 proc osutils:tk:files { tkloc theExtensions } {
1871   set Tfiles(source,nocdlpack)     {source pubinclude}
1872   set Tfiles(source,toolkit)       {}
1873   set Tfiles(source,executable)    {source pubinclude}
1874   set listloc [concat [osutils:tk:units $tkloc] $tkloc]
1875   #puts " listloc = $listloc"
1876
1877   set resultloc $listloc
1878   set lret {}
1879   foreach loc $resultloc {
1880     set utyp [_get_type $loc]
1881     #puts "\"$utyp\" \"$loc\""
1882     switch $utyp {
1883          "t" { set utyp "toolkit" }
1884          "n" { set utyp "nocdlpack" }
1885          "x" { set utyp "executable" }
1886          default { error "Error: Cannot determine type of unit $loc, check adm/UDLIST!" }
1887     }
1888     if [array exists map] { unset map }
1889     osutils:tk:loadunit $loc map
1890     #puts " loc = $loc === > [array names map]"
1891     set LType $Tfiles(source,${utyp})
1892     foreach typ [array names map] {
1893       if { [lsearch $LType $typ] == -1 } {
1894         unset map($typ)
1895       }
1896     }
1897     foreach type [array names map] {
1898       #puts $type
1899       foreach f $map($type) {
1900         #puts $f
1901         if { [lsearch $theExtensions [file extension $f]] != -1 } {
1902           lappend lret $f
1903         }
1904       }
1905     }
1906   }
1907   return $lret
1908 }
1909
1910 # Returns the list of all compilable files name in a toolkit.
1911 proc osutils:tk:cxxfiles { tkloc thePlatform } { return [osutils:tk:files $tkloc [osutils:compilable $thePlatform]] }
1912
1913 # Returns the list of all header files name in a toolkit.
1914 proc osutils:tk:hxxfiles { tkloc thePlatform } { return [osutils:tk:files $tkloc [osutils:fileExtensionsHeaders $thePlatform]] }
1915
1916 # Generate Visual Studio project file for executable
1917 proc osutils:vcprojx { theVcVer isUWP theOutDir theToolKit theGuidsMap } {
1918   set aVcFiles {}
1919   foreach f [osutils:tk:cxxfiles $theToolKit wnt] {
1920     set aProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 1]
1921
1922     set aProjName [file rootname [file tail $f]]
1923     set l_compilable [osutils:compilable wnt]
1924     regsub -all -- {__XQTNAM__} $aProjTmpl $aProjName aProjTmpl
1925
1926     upvar $theGuidsMap aGuidsMap
1927     if { ! [info exists aGuidsMap($aProjName)] } {
1928       set aGuidsMap($aProjName) [OS:genGUID]
1929     }
1930     regsub -all -- {__PROJECT_GUID__} $aProjTmpl $aGuidsMap($aProjName) aProjTmpl
1931
1932     set aUsedLibs [list]
1933     foreach tkx [osutils:commonUsedTK  $theToolKit] {
1934       lappend aUsedLibs "${tkx}.lib"
1935     }
1936
1937     osutils:usedOsLibs $theToolKit "wnt" aLibs aFrameworks
1938     foreach aLibIter $aLibs {
1939       lappend aUsedLibs "${aLibIter}.lib"
1940     }
1941
1942     # correct names of referred third-party libraries that are named with suffix
1943     # depending on VC version
1944     set aVCRTVer [string range $theVcVer 0 3]
1945     regsub -all -- {vc[0-9]+} $aUsedLibs $aVCRTVer aUsedLibs
1946
1947 #    puts "$aProjName requires  $aUsedLibs"
1948     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1949       set aUsedLibs [join $aUsedLibs {;}]
1950     }
1951     regsub -all -- {__TKDEP__} $aProjTmpl $aUsedLibs aProjTmpl
1952
1953     set aFilesSection ""
1954     set aVcFilesCxx(units) ""
1955         set aVcFilesHxx(units) ""
1956
1957     if { ![info exists written([file tail $f])] } {
1958       set written([file tail $f]) 1
1959
1960       if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1961         append aFilesSection [osutils:vcxproj:cxxfile $f ""]
1962         if { ! [info exists aVcFilesCxx($theToolKit)] } { lappend aVcFilesCxx(units) $theToolKit }
1963         lappend aVcFilesCxx($theToolKit) $f
1964       } else {
1965         append aFilesSection "\t\t\t<Filter\n"
1966         append aFilesSection "\t\t\t\tName=\"$theToolKit\"\n"
1967         append aFilesSection "\t\t\t\t>\n"
1968         append aFilesSection [osutils:vcproj:file $theVcVer $f ""]
1969         append aFilesSection "\t\t\t</Filter>"
1970       }
1971     } else {
1972       puts "Warning : in vcproj there are than one occurences for [file tail $f]"
1973     }
1974     #puts "$aProjTmpl $aFilesSection"
1975     set anIncPaths "..\\..\\..\\inc"
1976     regsub -all -- {__TKINC__}  $aProjTmpl $anIncPaths    aProjTmpl
1977     regsub -all -- {__FILES__}  $aProjTmpl $aFilesSection aProjTmpl
1978     regsub -all -- {__CONF__}   $aProjTmpl Application    aProjTmpl
1979
1980     regsub -all -- {__XQTEXT__} $aProjTmpl "exe" aProjTmpl
1981
1982     set aFile [open [set aVcFilePath [file join $theOutDir ${aProjName}.[osutils:vcproj:ext $theVcVer]]] w]
1983     fconfigure $aFile -translation crlf
1984     puts $aFile $aProjTmpl
1985     close $aFile
1986
1987     set aCommonSettingsFile "$aVcFilePath.user"
1988     lappend aVcFiles $aVcFilePath
1989
1990     # write filters file for vc10
1991     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1992       lappend aVcFiles [osutils:vcxproj:filters $theOutDir $aProjName aVcFilesCxx aVcFilesHxx]
1993     }
1994
1995     # write resource file
1996     lappend aVcFiles [osutils:readtemplate:rc $theOutDir $aProjName]
1997
1998     set aCommonSettingsFileTmpl ""
1999     if { "$theVcVer" == "vc7" || "$theVcVer" == "vc8" } {
2000       # nothing
2001     } elseif { "$theVcVer" == "vc9" } {
2002       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcproj.user.vc9x"]
2003     } else {
2004       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcxproj.user.vc10x"]
2005     }
2006     if { "$aCommonSettingsFileTmpl" != "" } {
2007       regsub -all -- {__VCVER__} $aCommonSettingsFileTmpl $aVCRTVer aCommonSettingsFileTmpl
2008
2009       set aFile [open [set aVcFilePath "$aCommonSettingsFile"] w]
2010       fconfigure $aFile -translation crlf
2011       puts $aFile $aCommonSettingsFileTmpl
2012       close $aFile
2013
2014       lappend aVcFiles "$aCommonSettingsFile"
2015     }
2016   }
2017   return $aVcFiles
2018 }
2019
2020 # Generate entry for one source file in Visual Studio 7 - 9 project file
2021 proc osutils:vcproj:file { theVcVer theFile theOptions } {
2022   append aText "\t\t\t\t<File\n"
2023   append aText "\t\t\t\t\tRelativePath=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
2024   if { $theOptions == "" } {
2025     append aText "\t\t\t\t</File>\n"
2026     return $aText
2027   }
2028
2029   append aText "\t\t\t\t\t<FileConfiguration\n"
2030   append aText "\t\t\t\t\t\tName=\"Release\|Win32\">\n"
2031   append aText "\t\t\t\t\t\t<Tool\n"
2032   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2033   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2034   foreach aParam $theOptions {
2035     append aText "$aParam "
2036   }
2037   append aText "\"\n"
2038   append aText "\t\t\t\t\t\t/>\n"
2039   append aText "\t\t\t\t\t</FileConfiguration>\n"
2040
2041   append aText "\t\t\t\t\t<FileConfiguration\n"
2042   append aText "\t\t\t\t\t\tName=\"Debug\|Win32\">\n"
2043   append aText "\t\t\t\t\t\t<Tool\n"
2044   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2045   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2046   foreach aParam $theOptions {
2047     append aText "$aParam "
2048   }
2049   append aText "\"\n"
2050   append aText "\t\t\t\t\t\t/>\n"
2051   append aText "\t\t\t\t\t</FileConfiguration>\n"
2052   if { "$theVcVer" == "vc7" } {
2053     append aText "\t\t\t\t</File>\n"
2054     return $aText
2055   }
2056
2057   append aText "\t\t\t\t\t<FileConfiguration\n"
2058   append aText "\t\t\t\t\t\tName=\"Release\|x64\">\n"
2059   append aText "\t\t\t\t\t\t<Tool\n"
2060   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2061   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2062   foreach aParam $theOptions {
2063     append aText "$aParam "
2064   }
2065   append aText "\"\n"
2066   append aText "\t\t\t\t\t\t/>\n"
2067   append aText "\t\t\t\t\t</FileConfiguration>\n"
2068
2069   append aText "\t\t\t\t\t<FileConfiguration\n"
2070   append aText "\t\t\t\t\t\tName=\"Debug\|x64\">\n"
2071   append aText "\t\t\t\t\t\t<Tool\n"
2072   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2073   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2074   foreach aParam $theOptions {
2075     append aText "$aParam "
2076   }
2077   append aText "\"\n"
2078   append aText "\t\t\t\t\t\t/>\n"
2079   append aText "\t\t\t\t\t</FileConfiguration>\n"
2080
2081   append aText "\t\t\t\t</File>\n"
2082   return $aText
2083 }
2084
2085 proc wokUtils:FILES:mkdir { d } {
2086     global tcl_version
2087     regsub -all {\.[^.]*} $tcl_version "" major
2088     if { $major == 8 } {
2089         file mkdir $d
2090     } else {
2091         if ![file exists $d] {
2092             if { "[info command mkdir]" == "mkdir" } {
2093                 mkdir -path $d
2094             } else {
2095                 puts stderr "wokUtils:FILES:mkdir : Error unable to find a mkdir command."
2096             }
2097         }
2098     }
2099     if [file exists $d] {
2100         return $d
2101     } else {
2102         return {}
2103     }
2104 }
2105
2106 # remove from listloc OpenCascade units indesirables on Unix
2107 proc osutils:justunix { listloc } {
2108   if { "$::tcl_platform(os)" == "Darwin" } {
2109     set goaway [list Xw WNT]
2110   } else {
2111     set goaway [list WNT]
2112   }
2113   return [osutils:juststation $goaway $listloc]
2114 }
2115
2116
2117 ####### CODEBLOCK ###################################################################
2118 # Function to generate Code Blocks workspace and project files
2119 proc OS:MKCBP { theOutDir theModules theAllSolution thePlatform theCmpl } {
2120   puts stderr "Generating project files for Code Blocks"
2121
2122   # Generate projects for toolkits and separate workspace for each module
2123   foreach aModule $theModules {
2124     OS:cworkspace          $aModule $aModule $theOutDir
2125     OS:cbp        $theCmpl $aModule          $theOutDir $thePlatform
2126   }
2127
2128   # Generate single workspace "OCCT" containing projects from all modules
2129   if { "$theAllSolution" != "" } {
2130     OS:cworkspace $theAllSolution $theModules $theOutDir
2131   }
2132
2133   puts "The Code Blocks workspace and project files are stored in the $theOutDir directory"
2134 }
2135
2136 # Generate Code Blocks projects
2137 proc OS:cbp { theCmpl theModules theOutDir thePlatform } {
2138   set aProjectFiles {}
2139   foreach aModule $theModules {
2140     foreach aToolKit [${aModule}:toolkits] {
2141       lappend aProjectFiles [osutils:cbptk $theCmpl $theOutDir $aToolKit $thePlatform]
2142     }
2143     foreach anExecutable [OS:executable ${aModule}] {
2144       lappend aProjectFiles [osutils:cbpx  $theCmpl $theOutDir $anExecutable $thePlatform]
2145     }
2146   }
2147   return $aProjectFiles
2148 }
2149
2150 # Generate Code::Blocks project file for ToolKit
2151 proc osutils:cbptk { theCmpl theOutDir theToolKit thePlatform} {
2152   set aUsedLibs     [list]
2153   set aFrameworks   [list]
2154   set anIncPaths    [list]
2155   set aTKDefines    [list]
2156   set aTKSrcFiles   [list]
2157
2158   # collect list of referred libraries to link with
2159   osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks
2160   set aDepToolkits [wokUtils:LIST:Purge [osutils:tk:close $theToolKit]]
2161   foreach tkx $aDepToolkits {
2162     lappend aUsedLibs "${tkx}"
2163   }
2164
2165   lappend anIncPaths "../../../inc"
2166   set listloc [osutils:tk:units $theToolKit]
2167
2168   if { [llength $listloc] == 0 } {
2169     set listloc $theToolKit
2170   }
2171
2172   if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2173     set resultloc [osutils:justwnt  $listloc]
2174   } else {
2175     set resultloc [osutils:justunix $listloc]
2176   }
2177   if [array exists written] { unset written }
2178   foreach fxlo $resultloc {
2179     set xlo       $fxlo
2180     set aSrcFiles [osutils:tk:cxxfiles $xlo $thePlatform]
2181     foreach aSrcFile [lsort $aSrcFiles] {
2182       if { ![info exists written([file tail $aSrcFile])] } {
2183         set written([file tail $aSrcFile]) 1
2184         lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2185       } else {
2186         puts "Warning : more than one occurences for [file tail $aSrcFile]"
2187       }
2188     }
2189
2190     # macros for correct DLL exports
2191 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2192 #      lappend aTKDefines "__${xlo}_DLL"
2193 #    }
2194   }
2195
2196   return [osutils:cbp $theCmpl $theOutDir $theToolKit $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines]
2197 }
2198
2199 # Generates Code Blocks workspace.
2200 proc OS:cworkspace { theSolName theModules theOutDir } {
2201   global path
2202   set aWsFilePath "${theOutDir}/${theSolName}.workspace"
2203   set aFile [open $aWsFilePath "w"]
2204   set isActiveSet 0
2205   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2206   puts $aFile "<CodeBlocks_workspace_file>"
2207   puts $aFile "\t<Workspace title=\"${theSolName}\">"
2208
2209   # collect list of projects to be created
2210   foreach aModule $theModules {
2211     # toolkits
2212     foreach aToolKit [osutils:tk:sort [${aModule}:toolkits]] {
2213       set aDependencies [LibToLink $aToolKit]
2214       if { [llength $aDependencies] == 0 } {
2215         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" />"
2216       } else {
2217         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" >"
2218         foreach aDepTk $aDependencies {
2219           puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2220         }
2221         puts $aFile "\t\t</Project>"
2222       }
2223     }
2224
2225     # executables, assume one project per cxx file...
2226     foreach aUnit [OS:executable ${aModule}] {
2227       set aUnitLoc $aUnit
2228       set src_files [_get_used_files $aUnit false]
2229       set aSrcFiles {}
2230       foreach s $src_files { 
2231         regexp {source ([^\s]+)} $s dummy name
2232         lappend aSrcFiles $name
2233       }
2234       foreach aSrcFile $aSrcFiles {
2235         set aFileExtension [file extension $aSrcFile]
2236         if { $aFileExtension == ".cxx" } {
2237           set aPrjName [file rootname $aSrcFile]
2238           set aDependencies [list]
2239           if {[file isdirectory $path/src/$aUnitLoc]} {
2240             set aDependencies [LibToLinkX $aUnitLoc [file rootname $aSrcFile]]
2241           }
2242           set anActiveState ""
2243           if { $isActiveSet == 0 } {
2244             set anActiveState " active=\"1\""
2245             set isActiveSet 1
2246           }
2247           if { [llength $aDependencies] == 0 } {
2248             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}/>"
2249           } else {
2250             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}>"
2251             foreach aDepTk $aDependencies {
2252               puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2253             }
2254             puts $aFile "\t\t</Project>"
2255           }
2256         }
2257       }
2258     }
2259   }
2260
2261   puts $aFile "\t</Workspace>"
2262   puts $aFile "</CodeBlocks_workspace_file>"
2263   close $aFile
2264
2265   return $aWsFilePath
2266 }
2267
2268 # Generate Code::Blocks project file for Executable
2269 proc osutils:cbpx { theCmpl theOutDir theToolKit thePlatform } {
2270   global path
2271   set aWokArch    "$::env(ARCH)"
2272
2273   set aCbpFiles {}
2274   foreach aSrcFile [osutils:tk:cxxfiles $theToolKit $thePlatform] {
2275     # collect list of referred libraries to link with
2276     set aUsedLibs     [list]
2277     set aFrameworks   [list]
2278     set anIncPaths    [list]
2279     set aTKDefines    [list]
2280     set aTKSrcFiles   [list]
2281     set aProjName [file rootname [file tail $aSrcFile]]
2282
2283     osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks
2284
2285     set aDepToolkits [LibToLinkX $theToolKit $aProjName]
2286     foreach tkx $aDepToolkits {
2287       if {[_get_type $tkx] == "t"} {
2288         lappend aUsedLibs "${tkx}"
2289       }
2290       if {[lsearch [glob -tails -directory "$path/src" -types d *] $tkx] == "-1"} {
2291         lappend aUsedLibs "${tkx}"
2292       }
2293     }
2294
2295     set WOKSteps_exec_link [_get_options lin WOKSteps_exec_link $theToolKit]
2296     if { [regexp {WOKStep_DLLink} $WOKSteps_exec_link] || [regexp {WOKStep_Libink} $WOKSteps_exec_link] } {
2297       set isExecutable "false"
2298     } else {
2299       set isExecutable "true"
2300     }
2301
2302     if { ![info exists written([file tail $aSrcFile])] } {
2303       set written([file tail $aSrcFile]) 1
2304       lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2305     } else {
2306       puts "Warning : in cbp there are more than one occurences for [file tail $aSrcFile]"
2307     }
2308
2309     # macros for correct DLL exports
2310 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2311 #      lappend aTKDefines "__${theToolKit}_DLL"
2312 #    }
2313
2314     # common include paths
2315     lappend anIncPaths "../../../inc"
2316
2317     lappend aCbpFiles [osutils:cbp $theCmpl $theOutDir $aProjName $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines $isExecutable]
2318   }
2319
2320   return $aCbpFiles
2321 }
2322
2323 # This function intended to generate Code::Blocks project file
2324 # @param theCmpl       - the compiler (gcc or msvc)
2325 # @param theOutDir     - output directory to place project file
2326 # @param theProjName   - project name
2327 # @param theSrcFiles   - list of source files
2328 # @param theLibsList   - dependencies (libraries  list)
2329 # @param theFrameworks - dependencies (frameworks list, Mac OS X specific)
2330 # @param theIncPaths   - header search paths
2331 # @param theDefines    - compiler macro definitions
2332 # @param theIsExe      - flag to indicate executable / library target
2333 proc osutils:cbp { theCmpl theOutDir theProjName thePlatform theSrcFiles theLibsList theFrameworks theIncPaths theDefines {theIsExe "false"} } {
2334   set aWokArch    "$::env(ARCH)"
2335
2336   set aCmplCbp "gcc"
2337   set aCmplFlags        [list]
2338   set aCmplFlagsRelease [list]
2339   set aCmplFlagsDebug   [list]
2340   set toPassArgsByFile 0
2341   set aLibPrefix "lib"
2342   set aPlatformAndCompiler "${thePlatform}/gcc"
2343   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } {
2344     set aPlatformAndCompiler "${thePlatform}/clang"
2345   }
2346   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" || "$thePlatform" == "qnx" } {
2347     set toPassArgsByFile 1
2348   }
2349   if { "$theCmpl" == "msvc" } {
2350     set aCmplCbp "msvc8"
2351     set aLibPrefix ""
2352   }
2353
2354   if { "$theCmpl" == "msvc" } {
2355     set aCmplFlags        "-arch:SSE2 -EHsc -W4 -MP"
2356     set aCmplFlagsRelease "-MD  -O2"
2357     set aCmplFlagsDebug   "-MDd -Od -Zi"
2358     lappend aCmplFlags    "-D_CRT_SECURE_NO_WARNINGS"
2359     lappend aCmplFlags    "-D_CRT_NONSTDC_NO_DEPRECATE"
2360   } elseif { "$theCmpl" == "gcc" } {
2361     if { "$thePlatform" != "qnx" } {
2362       set aCmplFlags      "-mmmx -msse -msse2 -mfpmath=sse"
2363     }
2364     set aCmplFlagsRelease "-O2"
2365     set aCmplFlagsDebug   "-O0 -g"
2366     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2367       lappend aCmplFlags "-std=gnu++0x"
2368       lappend aCmplFlags "-D_WIN32_WINNT=0x0501"
2369     } else {
2370       lappend aCmplFlags "-std=c++0x"
2371       lappend aCmplFlags "-fPIC"
2372       lappend aCmplFlags "-DOCC_CONVERT_SIGNALS"
2373     }
2374     lappend aCmplFlags   "-Wall"
2375     lappend aCmplFlags   "-fexceptions"
2376   }
2377   lappend aCmplFlagsRelease "-DNDEBUG"
2378   lappend aCmplFlagsRelease "-DNo_Exception"
2379   lappend aCmplFlagsDebug   "-D_DEBUG"
2380   if { "$thePlatform" == "qnx" } {
2381     lappend aCmplFlags "-D_QNX_SOURCE"
2382   }
2383
2384   set aCbpFilePath    "${theOutDir}/${theProjName}.cbp"
2385   set aLnkFileName    "${theProjName}_obj.link"
2386   set aLnkDebFileName "${theProjName}_objd.link"
2387   set aLnkFilePath    "${theOutDir}/${aLnkFileName}"
2388   set aLnkDebFilePath "${theOutDir}/${aLnkDebFileName}"
2389   set aFile [open $aCbpFilePath "w"]
2390   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2391   puts $aFile "<CodeBlocks_project_file>"
2392   puts $aFile "\t<FileVersion major=\"1\" minor=\"6\" />"
2393   puts $aFile "\t<Project>"
2394   puts $aFile "\t\t<Option title=\"$theProjName\" />"
2395   puts $aFile "\t\t<Option pch_mode=\"2\" />"
2396   puts $aFile "\t\t<Option compiler=\"$aCmplCbp\" />"
2397   puts $aFile "\t\t<Build>"
2398
2399   # Release target configuration
2400   puts $aFile "\t\t\t<Target title=\"Release\">"
2401   if { "$theIsExe" == "true" } {
2402     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bin/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2403     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2404   } else {
2405     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2406       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\" />"
2407     } else {
2408       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/lib/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2409     }
2410     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2411   }
2412   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/obj\" />"
2413   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2414   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2415   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2416     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2417   } else {
2418     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2419   }
2420
2421   # compiler options per TARGET (including defines)
2422   puts $aFile "\t\t\t\t<Compiler>"
2423   foreach aFlagIter $aCmplFlagsRelease {
2424     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2425   }
2426   foreach aMacro $theDefines {
2427     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2428   }
2429   puts $aFile "\t\t\t\t</Compiler>"
2430
2431   puts $aFile "\t\t\t\t<Linker>"
2432   if { $toPassArgsByFile == 1 } {
2433     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkFileName\" />"
2434   }
2435   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/lib\" />"
2436   if { "$thePlatform" == "mac" } {
2437     if { [ lsearch $theLibsList X11 ] >= 0} {
2438       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2439     }
2440   }
2441   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch})\" />"
2442   if { "$thePlatform" == "lin" } {
2443     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/lib\" />"
2444   }
2445   puts $aFile "\t\t\t\t</Linker>"
2446
2447   puts $aFile "\t\t\t</Target>"
2448
2449   # Debug target configuration
2450   puts $aFile "\t\t\t<Target title=\"Debug\">"
2451   if { "$theIsExe" == "true" } {
2452     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bind/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2453     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2454   } else {
2455     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2456       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\" />"
2457     } else {
2458       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/libd/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2459     }
2460     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2461   }
2462   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/objd\" />"
2463   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2464   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2465   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2466     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2467   } else {
2468     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2469   }
2470
2471   # compiler options per TARGET (including defines)
2472   puts $aFile "\t\t\t\t<Compiler>"
2473   foreach aFlagIter $aCmplFlagsDebug {
2474     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2475   }
2476   foreach aMacro $theDefines {
2477     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2478   }
2479   puts $aFile "\t\t\t\t</Compiler>"
2480
2481   puts $aFile "\t\t\t\t<Linker>"
2482   if { $toPassArgsByFile == 1 } {
2483     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkDebFileName\" />"
2484   }
2485   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/libd\" />"
2486   if { "$thePlatform" == "mac" } {
2487     if { [ lsearch $theLibsList X11 ] >= 0} {
2488       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2489     }
2490   }
2491   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch}D)\" />"
2492   if { "$thePlatform" == "lin" } {
2493     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/libd\" />"
2494   }
2495   puts $aFile "\t\t\t\t</Linker>"
2496
2497   puts $aFile "\t\t\t</Target>"
2498
2499   puts $aFile "\t\t</Build>"
2500
2501   # COMMON compiler options
2502   puts $aFile "\t\t<Compiler>"
2503   foreach aFlagIter $aCmplFlags {
2504     puts $aFile "\t\t\t<Add option=\"$aFlagIter\" />"
2505   }
2506   puts $aFile "\t\t\t<Add option=\"\$(CSF_OPT_CMPL)\" />"
2507   foreach anIncPath $theIncPaths {
2508     puts $aFile "\t\t\t<Add directory=\"$anIncPath\" />"
2509   }
2510   puts $aFile "\t\t</Compiler>"
2511
2512   # COMMON linker options
2513   puts $aFile "\t\t<Linker>"
2514   if { "$thePlatform" == "wnt" && "$theCmpl" == "gcc" } {
2515     puts $aFile "\t\t\t<Add option=\"-Wl,--export-all-symbols\" />"
2516   }
2517   foreach aFrameworkName $theFrameworks {
2518     if { "$aFrameworkName" != "" } {
2519       puts $aFile "\t\t\t<Add option=\"-framework $aFrameworkName\" />"
2520     }
2521   }
2522   foreach aLibName $theLibsList {
2523     if { "$aLibName" != "" } {
2524       if { "$theCmpl" == "msvc" } {
2525         puts $aFile "\t\t\t<Add library=\"${aLibName}.lib\" />"
2526       } else {
2527         puts $aFile "\t\t\t<Add library=\"${aLibName}\" />"
2528       }
2529     }
2530   }
2531   puts $aFile "\t\t</Linker>"
2532
2533   # list of sources
2534
2535   set aFileLnkObj ""
2536   set aFileLnkObjd ""
2537   set isFirstSrcFile 1
2538   if { $toPassArgsByFile == 1 } {
2539     set aFileLnkObj  [open $aLnkFilePath    "w"]
2540     set aFileLnkObjd [open $aLnkDebFilePath "w"]
2541   }
2542
2543   foreach aSrcFile $theSrcFiles {
2544     if {[string equal -nocase [file extension $aSrcFile] ".mm"]} {
2545       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2546       puts $aFile "\t\t\t<Option compile=\"1\" />"
2547       puts $aFile "\t\t\t<Option link=\"1\" />"
2548       puts $aFile "\t\t</Unit>"
2549     } elseif {[string equal -nocase [file extension $aSrcFile] ".c"]} {
2550       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2551       puts $aFile "\t\t\t<Option compilerVar=\"CC\" />"
2552       puts $aFile "\t\t</Unit>"
2553     } elseif { $toPassArgsByFile == 1 && $isFirstSrcFile == 0 && [string equal -nocase [file extension $aSrcFile] ".cxx" ] } {
2554       # pass at list single source file to Code::Blocks as is
2555       # and pack the list of other files into the dedicated file to workaround process arguments limits on systems like Windows
2556       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2557       puts $aFile "\t\t\t<Option link=\"0\" />"
2558       puts $aFile "\t\t</Unit>"
2559
2560       set aFileObj  [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/obj/src/"]  $aSrcFile]]
2561       set aFileObjd [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/objd/src/"] $aSrcFile]]
2562       puts -nonewline $aFileLnkObj  "$aFileObj "
2563       puts -nonewline $aFileLnkObjd "$aFileObjd "
2564     } else {
2565       puts $aFile "\t\t<Unit filename=\"$aSrcFile\" />"
2566       set isFirstSrcFile 0
2567     }
2568   }
2569
2570   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2571     close $aFileLnkObj
2572     close $aFileLnkObjd
2573   }
2574
2575   puts $aFile "\t</Project>"
2576   puts $aFile "</CodeBlocks_project_file>"
2577   close $aFile
2578
2579   return $aCbpFilePath
2580 }
2581
2582 # Define libraries to link using only EXTERNLIB file
2583 proc LibToLinkX {thePackage theDummyName} {
2584   set aToolKits [LibToLink $thePackage]
2585   return $aToolKits
2586 }
2587
2588 # Function to generate Xcode workspace and project files
2589 proc OS:MKXCD { theOutDir {theModules {}} {theAllSolution ""} {theLibType "dynamic"} {thePlatform ""} } {
2590
2591   puts stderr "Generating project files for Xcode"
2592
2593   # Generate projects for toolkits and separate workspace for each module
2594   foreach aModule $theModules {
2595     OS:xcworkspace $aModule $aModule $theOutDir
2596     OS:xcodeproj   $aModule          $theOutDir ::THE_GUIDS_LIST $theLibType $thePlatform
2597   }
2598
2599   # Generate single workspace "OCCT" containing projects from all modules
2600   if { "$theAllSolution" != "" } {
2601     OS:xcworkspace $theAllSolution $theModules $theOutDir
2602   }
2603 }
2604
2605 # Generates toolkits sections for Xcode workspace file.
2606 proc OS:xcworkspace:toolkits { theModule } {
2607   set aBuff ""
2608
2609   # Adding toolkits for module in workspace.
2610   foreach aToolKit [osutils:tk:sort [${theModule}:toolkits]] {
2611     append aBuff "         <FileRef\n"
2612     append aBuff "            location = \"group:${aToolKit}.xcodeproj\">\n"
2613     append aBuff "         </FileRef>\n"
2614   }
2615
2616   # Adding executables for module, assume one project per cxx file...
2617   foreach aUnit [OS:executable ${theModule}] {
2618     set aUnitLoc $aUnit
2619     set src_files [_get_used_files $aUnit false]
2620     set aSrcFiles {}
2621     foreach s $src_files {
2622       regexp {source ([^\s]+)} $s dummy name
2623       lappend aSrcFiles $name
2624     }
2625     foreach aSrcFile $aSrcFiles {
2626       set aFileExtension [file extension $aSrcFile]
2627       if { $aFileExtension == ".cxx" } {
2628         set aPrjName [file rootname $aSrcFile]
2629         append aBuff "         <FileRef\n"
2630         append aBuff "            location = \"group:${aPrjName}.xcodeproj\">\n"
2631         append aBuff "         </FileRef>\n"
2632       }
2633     }
2634   }
2635
2636   # Removing unnecessary newline character from the end.
2637   set aBuff [string replace $aBuff end end]
2638   return $aBuff
2639 }
2640
2641 # Generates workspace files for Xcode.
2642 proc OS:xcworkspace { theWorkspaceName theModules theOutDir } {
2643   # Creating workspace directory for Xcode.
2644   set aWorkspaceDir "${theOutDir}/${theWorkspaceName}.xcworkspace"
2645   wokUtils:FILES:mkdir $aWorkspaceDir
2646   if { ! [file exists $aWorkspaceDir] } {
2647     puts stderr "Error: Could not create workspace directory \"$aWorkspaceDir\""
2648     return
2649   }
2650
2651   # Creating workspace file.
2652   set aWsFilePath "${aWorkspaceDir}/contents.xcworkspacedata"
2653   set aFile [open $aWsFilePath "w"]
2654
2655   # Adding header and section for main Group.
2656   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
2657   puts $aFile "<Workspace"
2658   puts $aFile "   version = \"1.0\">"
2659   puts $aFile "   <Group"
2660   puts $aFile "      location = \"container:\""
2661   puts $aFile "      name = \"${theWorkspaceName}\">"
2662
2663   # Adding modules.
2664   if { [llength "$theModules"] > 1 } {
2665     foreach aModule $theModules {
2666       puts $aFile "      <Group"
2667       puts $aFile "         location = \"container:\""
2668       puts $aFile "         name = \"${aModule}\">"
2669       puts $aFile [OS:xcworkspace:toolkits $aModule]
2670       puts $aFile "      </Group>"
2671     }
2672   } else {
2673     puts $aFile [OS:xcworkspace:toolkits $theModules]
2674   }
2675
2676   # Adding footer.
2677   puts $aFile "   </Group>"
2678   puts $aFile "</Workspace>"
2679   close $aFile
2680 }
2681
2682 # Generates Xcode project files.
2683 proc OS:xcodeproj { theModules theOutDir theGuidsMap theLibType thePlatform} {
2684   upvar $theGuidsMap aGuidsMap
2685
2686   set isStatic 0
2687   if { "$theLibType" == "static" } {
2688     set isStatic 1
2689   } elseif { "$thePlatform" == "ios" } {
2690     set isStatic 1
2691   }
2692
2693   set aProjectFiles {}
2694   foreach aModule $theModules {
2695     foreach aToolKit [${aModule}:toolkits] {
2696       lappend aProjectFiles [osutils:xcdtk $theOutDir $aToolKit     aGuidsMap $isStatic $thePlatform "dylib"]
2697     }
2698     foreach anExecutable [OS:executable ${aModule}] {
2699       lappend aProjectFiles [osutils:xcdtk $theOutDir $anExecutable aGuidsMap $isStatic $thePlatform "executable"]
2700     }
2701   }
2702   return $aProjectFiles
2703 }
2704
2705 # Generates dependencies section for Xcode project files.
2706 proc osutils:xcdtk:deps {theToolKit theTargetType theGuidsMap theFileRefSection theDepsGuids theDepsRefGuids thePlatform theIsStatic} {
2707   upvar $theGuidsMap         aGuidsMap
2708   upvar $theFileRefSection   aFileRefSection
2709   upvar $theDepsGuids        aDepsGuids
2710   upvar $theDepsRefGuids     aDepsRefGuids
2711
2712   set aBuildFileSection ""
2713   set aUsedLibs         [wokUtils:LIST:Purge [osutils:tk:close $theToolKit]]
2714   set aDepToolkits      [lappend [wokUtils:LIST:Purge [osutils:tk:close $theToolKit]] $theToolKit]
2715
2716   if { "$theTargetType" == "executable" } {
2717     set aFile [osutils:tk:cxxfiles $theToolKit mac]
2718     set aProjName [file rootname [file tail $aFile]]
2719     set aDepToolkits [LibToLinkX $theToolKit $aProjName]
2720   }
2721
2722   set aLibExt "dylib"
2723   if { $theIsStatic == 1 } {
2724     set aLibExt "a"
2725     if { "$theTargetType" != "executable" } {
2726       return $aBuildFileSection
2727     }
2728   }
2729
2730   osutils:usedOsLibs $theToolKit $thePlatform aLibs aFrameworks
2731   set aUsedLibs [concat $aUsedLibs $aLibs]
2732   set aUsedLibs [concat $aUsedLibs $aFrameworks]
2733   foreach tkx $aUsedLibs {
2734     set aDepLib    "${tkx}_Dep"
2735     set aDepLibRef "${tkx}_DepRef"
2736
2737     if { ! [info exists aGuidsMap($aDepLib)] } {
2738       set aGuidsMap($aDepLib) [OS:genGUID "xcd"]
2739     }
2740     if { ! [info exists aGuidsMap($aDepLibRef)] } {
2741       set aGuidsMap($aDepLibRef) [OS:genGUID "xcd"]
2742     }
2743
2744     append aBuildFileSection "\t\t$aGuidsMap($aDepLib) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aDepLibRef) ; \};\n"
2745     if {[lsearch -nocase $aFrameworks $tkx] == -1} {
2746       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = file; name = lib${tkx}.${aLibExt}; path = lib${tkx}.${aLibExt}; sourceTree = \"<group>\"; \};\n"
2747     } else {
2748       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ${tkx}.framework; path = /System/Library/Frameworks/${tkx}.framework; sourceTree = \"<absolute>\"; \};\n"
2749     }
2750     append aDepsGuids        "\t\t\t\t$aGuidsMap($aDepLib) ,\n"
2751     append aDepsRefGuids     "\t\t\t\t$aGuidsMap($aDepLibRef) ,\n"
2752   }
2753
2754   return $aBuildFileSection
2755 }
2756
2757 # Generates PBXBuildFile and PBXGroup sections for project file.
2758 proc osutils:xcdtk:sources {theToolKit theTargetType theSrcFileRefSection theGroupSection thePackageGuids theSrcFileGuids theGuidsMap theIncPaths} {
2759   upvar $theSrcFileRefSection aSrcFileRefSection
2760   upvar $theGroupSection      aGroupSection
2761   upvar $thePackageGuids      aPackagesGuids
2762   upvar $theSrcFileGuids      aSrcFileGuids
2763   upvar $theGuidsMap          aGuidsMap
2764   upvar $theIncPaths          anIncPaths
2765
2766   set listloc [osutils:tk:units $theToolKit]
2767   set resultloc [osutils:justunix $listloc]
2768   set aBuildFileSection ""
2769   set aPackages [lsort -nocase $resultloc]
2770   if { "$theTargetType" == "executable" } {
2771     set aPackages [list "$theToolKit"]
2772   }
2773
2774   # Generating PBXBuildFile, PBXGroup sections and groups for each package.
2775   foreach fxlo $aPackages {
2776     set xlo       $fxlo
2777     set aPackage "${xlo}_Package"
2778     set aSrcFileRefGuids ""
2779     if { ! [info exists aGuidsMap($aPackage)] } {
2780       set aGuidsMap($aPackage) [OS:genGUID "xcd"]
2781     }
2782
2783     set aSrcFiles [osutils:tk:cxxfiles $xlo mac]
2784     foreach aSrcFile [lsort $aSrcFiles] {
2785       set aFileExt "sourcecode.cpp.cpp"
2786
2787       if { [file extension $aSrcFile] == ".c" } {
2788         set aFileExt "sourcecode.c.c"
2789       } elseif { [file extension $aSrcFile] == ".mm" } {
2790         set aFileExt "sourcecode.cpp.objcpp"
2791       }
2792
2793       if { ! [info exists aGuidsMap($aSrcFile)] } {
2794         set aGuidsMap($aSrcFile) [OS:genGUID "xcd"]
2795       }
2796       set aSrcFileRef "${aSrcFile}_Ref"
2797       if { ! [info exists aGuidsMap($aSrcFileRef)] } {
2798         set aGuidsMap($aSrcFileRef) [OS:genGUID "xcd"]
2799       }
2800       if { ! [info exists written([file tail $aSrcFile])] } {
2801         set written([file tail $aSrcFile]) 1
2802         append aBuildFileSection  "\t\t$aGuidsMap($aSrcFile) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aSrcFileRef) ;\};\n"
2803         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"
2804         append aSrcFileGuids      "\t\t\t\t$aGuidsMap($aSrcFile) ,\n"
2805         append aSrcFileRefGuids   "\t\t\t\t$aGuidsMap($aSrcFileRef) ,\n"
2806       } else {
2807         puts "Warning : more than one occurences for [file tail $aSrcFile]"
2808       }
2809     }
2810
2811     append aGroupSection "\t\t$aGuidsMap($aPackage) = \{\n"
2812     append aGroupSection "\t\t\tisa = PBXGroup;\n"
2813     append aGroupSection "\t\t\tchildren = (\n"
2814     append aGroupSection $aSrcFileRefGuids
2815     append aGroupSection "\t\t\t);\n"
2816     append aGroupSection "\t\t\tname = $xlo;\n"
2817     append aGroupSection "\t\t\tsourceTree = \"<group>\";\n"
2818     append aGroupSection "\t\t\};\n"
2819
2820     # Storing packages IDs for adding them later as a child of toolkit
2821     append aPackagesGuids "\t\t\t\t$aGuidsMap($aPackage) ,\n"
2822   }
2823
2824   # Removing unnecessary newline character from the end.
2825   set aPackagesGuids [string replace $aPackagesGuids end end]
2826
2827   return $aBuildFileSection
2828 }
2829
2830 # Creates folders structure and all necessary files for Xcode project.
2831 proc osutils:xcdtk { theOutDir theToolKit theGuidsMap theIsStatic thePlatform {theTargetType "dylib"} } {
2832   set aPBXBuildPhase "Headers"
2833   set aRunOnlyForDeployment "0"
2834   set aProductType "library.dynamic"
2835   set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = dylib;"
2836   set anExecPrefix "\t\t\t\tEXECUTABLE_PREFIX = lib;"
2837   set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = dylib;"
2838   set aTKDefines [list "OCC_CONVERT_SIGNALS"]
2839   if { $theIsStatic == 1 } {
2840     lappend aTKDefines "OCCT_NO_PLUGINS"
2841   }
2842
2843   if { "$theTargetType" == "executable" } {
2844     set aPBXBuildPhase "CopyFiles"
2845     set aRunOnlyForDeployment "1"
2846     set aProductType "tool"
2847     set anExecExtension ""
2848     set anExecPrefix ""
2849     set aWrapperExtension ""
2850   } elseif { $theIsStatic == 1 } {
2851     set aProductType "library.static"
2852     set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = a;"
2853     set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = a;"
2854   }
2855
2856   set aUsername [exec whoami]
2857
2858   # Creation of folders for Xcode projectP.
2859   set aToolkitDir "${theOutDir}/${theToolKit}.xcodeproj"
2860   wokUtils:FILES:mkdir $aToolkitDir
2861   if { ! [file exists $aToolkitDir] } {
2862     puts stderr "Error: Could not create project directory \"$aToolkitDir\""
2863     return
2864   }
2865
2866   set aUserDataDir "${aToolkitDir}/xcuserdata"
2867   wokUtils:FILES:mkdir $aUserDataDir
2868   if { ! [file exists $aUserDataDir] } {
2869     puts stderr "Error: Could not create xcuserdata directorty in \"$aToolkitDir\""
2870     return
2871   }
2872
2873   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
2874   wokUtils:FILES:mkdir $aUserDataDir
2875   if { ! [file exists $aUserDataDir] } {
2876     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directorty in \"$aToolkitDir\"/xcuserdata"
2877     return
2878   }
2879
2880   set aSchemesDir "${aUserDataDir}/xcschemes"
2881   wokUtils:FILES:mkdir $aSchemesDir
2882   if { ! [file exists $aSchemesDir] } {
2883     puts stderr "Error: Could not create xcschemes directorty in \"$aUserDataDir\""
2884     return
2885   }
2886   # End of folders creation.
2887
2888   # Generating GUID for tookit.
2889   upvar $theGuidsMap aGuidsMap
2890   if { ! [info exists aGuidsMap($theToolKit)] } {
2891     set aGuidsMap($theToolKit) [OS:genGUID "xcd"]
2892   }
2893
2894   # Creating xcscheme file for toolkit from template.
2895   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcd"]
2896   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theToolKit aXcschemeTmpl
2897   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theToolKit) aXcschemeTmpl
2898   set aXcschemeFile [open "$aSchemesDir/${theToolKit}.xcscheme"  "w"]
2899   puts $aXcschemeFile $aXcschemeTmpl
2900   close $aXcschemeFile
2901
2902   # Creating xcschememanagement.plist file for toolkit from template.
2903   set aPlistTmpl [osutils:readtemplate "plist" "xcd"]
2904   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theToolKit aPlistTmpl
2905   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theToolKit) aPlistTmpl
2906   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
2907   puts $aPlistFile $aPlistTmpl
2908   close $aPlistFile
2909
2910   # Creating project.pbxproj file for toolkit.
2911   set aPbxprojFile [open "$aToolkitDir/project.pbxproj" "w"]
2912   puts $aPbxprojFile "// !\$*UTF8*\$!"
2913   puts $aPbxprojFile "\{"
2914   puts $aPbxprojFile "\tarchiveVersion = 1;"
2915   puts $aPbxprojFile "\tclasses = \{"
2916   puts $aPbxprojFile "\t\};"
2917   puts $aPbxprojFile "\tobjectVersion = 46;"
2918   puts $aPbxprojFile "\tobjects = \{\n"
2919
2920   # Begin PBXBuildFile section
2921   set aPackagesGuids ""
2922   set aGroupSection ""
2923   set aSrcFileRefSection ""
2924   set aSrcFileGuids ""
2925   set aDepsFileRefSection ""
2926   set aDepsGuids ""
2927   set aDepsRefGuids ""
2928   set anIncPaths [list "../../../inc"]
2929   set anLibPaths ""
2930
2931   if { [info exists ::env(CSF_OPT_INC)] } {
2932     set anIncCfg [split "$::env(CSF_OPT_INC)" ":"]
2933     foreach anIncCfgPath $anIncCfg {
2934       lappend anIncPaths $anIncCfgPath
2935     }
2936   }
2937   if { [info exists ::env(CSF_OPT_LIB64)] } {
2938     set anLibCfg [split "$::env(CSF_OPT_LIB64)" ":"]
2939     foreach anLibCfgPath $anLibCfg {
2940       lappend anLibPaths $anLibCfgPath
2941     }
2942   }
2943
2944   puts $aPbxprojFile [osutils:xcdtk:sources $theToolKit $theTargetType aSrcFileRefSection aGroupSection aPackagesGuids aSrcFileGuids aGuidsMap anIncPaths]
2945   puts $aPbxprojFile [osutils:xcdtk:deps    $theToolKit $theTargetType aGuidsMap aDepsFileRefSection aDepsGuids aDepsRefGuids $thePlatform $theIsStatic]
2946   # End PBXBuildFile section
2947
2948   # Begin PBXFileReference section
2949   set aToolkitLib "lib${theToolKit}.dylib"
2950   set aPath "$aToolkitLib"
2951   if { "$theTargetType" == "executable" } {
2952     set aPath "$theToolKit"
2953   } elseif { $theIsStatic == 1 } {
2954     set aToolkitLib "lib${theToolKit}.a"
2955   }
2956
2957   if { ! [info exists aGuidsMap($aToolkitLib)] } {
2958     set aGuidsMap($aToolkitLib) [OS:genGUID "xcd"]
2959   }
2960
2961   puts $aPbxprojFile "\t\t$aGuidsMap($aToolkitLib) = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.${theTargetType}\"; includeInIndex = 0; path = $aPath; sourceTree = BUILT_PRODUCTS_DIR; };\n"
2962   puts $aPbxprojFile $aSrcFileRefSection
2963   puts $aPbxprojFile $aDepsFileRefSection
2964   # End PBXFileReference section
2965
2966
2967   # Begin PBXFrameworksBuildPhase section
2968   set aTkFrameworks "${theToolKit}_Frameworks"
2969   if { ! [info exists aGuidsMap($aTkFrameworks)] } {
2970     set aGuidsMap($aTkFrameworks) [OS:genGUID "xcd"]
2971   }
2972
2973   puts $aPbxprojFile "\t\t$aGuidsMap($aTkFrameworks) = \{"
2974   puts $aPbxprojFile "\t\t\tisa = PBXFrameworksBuildPhase;"
2975   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
2976   puts $aPbxprojFile "\t\t\tfiles = ("
2977   puts $aPbxprojFile $aDepsGuids
2978   puts $aPbxprojFile "\t\t\t);"
2979   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
2980   puts $aPbxprojFile "\t\t\};\n"
2981   # End PBXFrameworksBuildPhase section
2982
2983   # Begin PBXGroup section
2984   set aTkPBXGroup "${theToolKit}_PBXGroup"
2985   if { ! [info exists aGuidsMap($aTkPBXGroup)] } {
2986     set aGuidsMap($aTkPBXGroup) [OS:genGUID "xcd"]
2987   }
2988
2989   set aTkSrcGroup "${theToolKit}_SrcGroup"
2990   if { ! [info exists aGuidsMap($aTkSrcGroup)] } {
2991     set aGuidsMap($aTkSrcGroup) [OS:genGUID "xcd"]
2992   }
2993
2994   puts $aPbxprojFile $aGroupSection
2995   puts $aPbxprojFile "\t\t$aGuidsMap($aTkPBXGroup) = \{"
2996   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
2997   puts $aPbxprojFile "\t\t\tchildren = ("
2998   puts $aPbxprojFile $aDepsRefGuids
2999   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSrcGroup) ,"
3000   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aToolkitLib) ,"
3001   puts $aPbxprojFile "\t\t\t);"
3002   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
3003   puts $aPbxprojFile "\t\t\};"
3004   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSrcGroup) = \{"
3005   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
3006   puts $aPbxprojFile "\t\t\tchildren = ("
3007   puts $aPbxprojFile $aPackagesGuids
3008   puts $aPbxprojFile "\t\t\t);"
3009   puts $aPbxprojFile "\t\t\tname = \"Source files\";"
3010   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
3011   puts $aPbxprojFile "\t\t\};\n"
3012   # End PBXGroup section
3013
3014   # Begin PBXHeadersBuildPhase section
3015   set aTkHeaders "${theToolKit}_Headers"
3016   if { ! [info exists aGuidsMap($aTkHeaders)] } {
3017     set aGuidsMap($aTkHeaders) [OS:genGUID "xcd"]
3018   }
3019
3020   puts $aPbxprojFile "\t\t$aGuidsMap($aTkHeaders) = \{"
3021   puts $aPbxprojFile "\t\t\tisa = PBX${aPBXBuildPhase}BuildPhase;"
3022   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3023   puts $aPbxprojFile "\t\t\tfiles = ("
3024   puts $aPbxprojFile "\t\t\t);"
3025   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = ${aRunOnlyForDeployment};"
3026   puts $aPbxprojFile "\t\t\};\n"
3027   # End PBXHeadersBuildPhase section
3028
3029   # Begin PBXNativeTarget section
3030   set aTkBuildCfgListNativeTarget "${theToolKit}_BuildCfgListNativeTarget"
3031   if { ! [info exists aGuidsMap($aTkBuildCfgListNativeTarget)] } {
3032     set aGuidsMap($aTkBuildCfgListNativeTarget) [OS:genGUID "xcd"]
3033   }
3034
3035   set aTkSources "${theToolKit}_Sources"
3036   if { ! [info exists aGuidsMap($aTkSources)] } {
3037     set aGuidsMap($aTkSources) [OS:genGUID "xcd"]
3038   }
3039
3040   puts $aPbxprojFile "\t\t$aGuidsMap($theToolKit) = \{"
3041   puts $aPbxprojFile "\t\t\tisa = PBXNativeTarget;"
3042   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListNativeTarget) ;"
3043   puts $aPbxprojFile "\t\t\tbuildPhases = ("
3044   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSources) ,"
3045   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkFrameworks) ,"
3046   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkHeaders) ,"
3047   puts $aPbxprojFile "\t\t\t);"
3048   puts $aPbxprojFile "\t\t\tbuildRules = ("
3049   puts $aPbxprojFile "\t\t\t);"
3050   puts $aPbxprojFile "\t\t\tdependencies = ("
3051   puts $aPbxprojFile "\t\t\t);"
3052   puts $aPbxprojFile "\t\t\tname = $theToolKit;"
3053   puts $aPbxprojFile "\t\t\tproductName = $theToolKit;"
3054   puts $aPbxprojFile "\t\t\tproductReference = $aGuidsMap($aToolkitLib) ;"
3055   puts $aPbxprojFile "\t\t\tproductType = \"com.apple.product-type.${aProductType}\";"
3056   puts $aPbxprojFile "\t\t\};\n"
3057   # End PBXNativeTarget section
3058
3059   # Begin PBXProject section
3060   set aTkProjectObj "${theToolKit}_ProjectObj"
3061   if { ! [info exists aGuidsMap($aTkProjectObj)] } {
3062     set aGuidsMap($aTkProjectObj) [OS:genGUID "xcd"]
3063   }
3064
3065   set aTkBuildCfgListProj "${theToolKit}_BuildCfgListProj"
3066   if { ! [info exists aGuidsMap($aTkBuildCfgListProj)] } {
3067     set aGuidsMap($aTkBuildCfgListProj) [OS:genGUID "xcd"]
3068   }
3069
3070   puts $aPbxprojFile "\t\t$aGuidsMap($aTkProjectObj) = \{"
3071   puts $aPbxprojFile "\t\t\tisa = PBXProject;"
3072   puts $aPbxprojFile "\t\t\tattributes = \{"
3073   puts $aPbxprojFile "\t\t\t\tLastUpgradeCheck = 0430;"
3074   puts $aPbxprojFile "\t\t\t\};"
3075   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListProj) ;"
3076   puts $aPbxprojFile "\t\t\tcompatibilityVersion = \"Xcode 3.2\";"
3077   puts $aPbxprojFile "\t\t\tdevelopmentRegion = English;"
3078   puts $aPbxprojFile "\t\t\thasScannedForEncodings = 0;"
3079   puts $aPbxprojFile "\t\t\tknownRegions = ("
3080   puts $aPbxprojFile "\t\t\t\ten,"
3081   puts $aPbxprojFile "\t\t\t);"
3082   puts $aPbxprojFile "\t\t\tmainGroup = $aGuidsMap($aTkPBXGroup);"
3083   puts $aPbxprojFile "\t\t\tproductRefGroup = $aGuidsMap($aTkPBXGroup);"
3084   puts $aPbxprojFile "\t\t\tprojectDirPath = \"\";"
3085   puts $aPbxprojFile "\t\t\tprojectRoot = \"\";"
3086   puts $aPbxprojFile "\t\t\ttargets = ("
3087   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($theToolKit) ,"
3088   puts $aPbxprojFile "\t\t\t);"
3089   puts $aPbxprojFile "\t\t\};\n"
3090   # End PBXProject section
3091
3092   # Begin PBXSourcesBuildPhase section
3093   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSources) = \{"
3094   puts $aPbxprojFile "\t\t\tisa = PBXSourcesBuildPhase;"
3095   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3096   puts $aPbxprojFile "\t\t\tfiles = ("
3097   puts $aPbxprojFile $aSrcFileGuids
3098   puts $aPbxprojFile "\t\t\t);"
3099   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
3100   puts $aPbxprojFile "\t\t\};\n"
3101   # End PBXSourcesBuildPhase section
3102
3103   # Begin XCBuildConfiguration section
3104   set aTkDebugProject "${theToolKit}_DebugProject"
3105   if { ! [info exists aGuidsMap($aTkDebugProject)] } {
3106     set aGuidsMap($aTkDebugProject) [OS:genGUID "xcd"]
3107   }
3108
3109   set aTkReleaseProject "${theToolKit}_ReleaseProject"
3110   if { ! [info exists aGuidsMap($aTkReleaseProject)] } {
3111     set aGuidsMap($aTkReleaseProject) [OS:genGUID "xcd"]
3112   }
3113
3114   set aTkDebugNativeTarget "${theToolKit}_DebugNativeTarget"
3115   if { ! [info exists aGuidsMap($aTkDebugNativeTarget)] } {
3116     set aGuidsMap($aTkDebugNativeTarget) [OS:genGUID "xcd"]
3117   }
3118
3119   set aTkReleaseNativeTarget "${theToolKit}_ReleaseNativeTarget"
3120   if { ! [info exists aGuidsMap($aTkReleaseNativeTarget)] } {
3121     set aGuidsMap($aTkReleaseNativeTarget) [OS:genGUID "xcd"]
3122   }
3123
3124   # Debug target
3125   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugProject) = \{"
3126   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3127   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3128
3129   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;"
3130   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3131   if { "$thePlatform" == "ios" } {
3132     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3133     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3134     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3135     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3136   }
3137   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3138   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3139   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3140   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = NO;"
3141   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3142   puts $aPbxprojFile "\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;"
3143   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3144   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;"
3145   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3146   puts $aPbxprojFile "\t\t\t\t\t\"DEBUG=1\","
3147   puts $aPbxprojFile "\t\t\t\t\t\"\$\(inherited\)\","
3148   puts $aPbxprojFile "\t\t\t\t);"
3149   puts $aPbxprojFile "\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;"
3150   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3151   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3152   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3153   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3154   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3155   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64D)\"; "
3156   if { "$thePlatform" == "ios" } {
3157     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = NO;"
3158     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3159   } else {
3160     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = YES;"
3161   }
3162   puts $aPbxprojFile "\t\t\t\};"
3163
3164   puts $aPbxprojFile "\t\t\tname = Debug;"
3165   puts $aPbxprojFile "\t\t\};"
3166
3167   # Release target
3168   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseProject) = \{"
3169   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3170   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3171
3172   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";"
3173   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3174   if { "$thePlatform" == "ios" } {
3175     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3176     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3177     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3178     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3179   }
3180   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3181   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3182   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3183   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = YES;"
3184   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3185   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3186   puts $aPbxprojFile "\t\t\t\tDEAD_CODE_STRIPPING = NO;"
3187   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 2;"
3188   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3189   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3190   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3191   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3192   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3193   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64)\";"
3194   if { "$thePlatform" == "ios" } {
3195     puts $aPbxprojFile "\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;"
3196     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3197   }
3198   puts $aPbxprojFile "\t\t\t\};"
3199   puts $aPbxprojFile "\t\t\tname = Release;"
3200   puts $aPbxprojFile "\t\t\};"
3201   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugNativeTarget) = \{"
3202   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3203   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3204   puts $aPbxprojFile "${anExecExtension}"
3205   puts $aPbxprojFile "${anExecPrefix}"
3206   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3207   foreach aMacro $aTKDefines {
3208     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3209   }
3210   puts $aPbxprojFile "\t\t\t\t);"
3211
3212   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3213   foreach anIncPath $anIncPaths {
3214     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3215   }
3216   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3217   puts $aPbxprojFile "\t\t\t\t);"
3218
3219   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3220   foreach anLibPath $anLibPaths {
3221     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3222   }
3223   puts $aPbxprojFile "\t\t\t\t);"
3224
3225   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3226   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3227   puts $aPbxprojFile "\t\t\t\t);"
3228   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3229   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3230   puts $aPbxprojFile "\t\t\t\t);"
3231   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3232   set anUserHeaderSearchPath "\t\t\t\tUSER_HEADER_SEARCH_PATHS = \""
3233   foreach anIncPath $anIncPaths {
3234     append anUserHeaderSearchPath " ${anIncPath}"
3235   }
3236   append anUserHeaderSearchPath "\";"
3237   puts $aPbxprojFile $anUserHeaderSearchPath
3238   puts $aPbxprojFile "${aWrapperExtension}"
3239   puts $aPbxprojFile "\t\t\t\};"
3240   puts $aPbxprojFile "\t\t\tname = Debug;"
3241   puts $aPbxprojFile "\t\t\};"
3242   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseNativeTarget) = \{"
3243   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3244   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3245   puts $aPbxprojFile "${anExecExtension}"
3246   puts $aPbxprojFile "${anExecPrefix}"
3247   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3248   foreach aMacro $aTKDefines {
3249     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3250   }
3251   puts $aPbxprojFile "\t\t\t\t);"
3252   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3253   foreach anIncPath $anIncPaths {
3254     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3255   }
3256   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3257   puts $aPbxprojFile "\t\t\t\t);"
3258
3259   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3260   foreach anLibPath $anLibPaths {
3261     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3262   }
3263   puts $aPbxprojFile "\t\t\t\t);"
3264
3265   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3266   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3267   puts $aPbxprojFile "\t\t\t\t);"
3268   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3269   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3270   puts $aPbxprojFile "\t\t\t\t);"
3271   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3272   puts $aPbxprojFile $anUserHeaderSearchPath
3273   puts $aPbxprojFile "${aWrapperExtension}"
3274   puts $aPbxprojFile "\t\t\t\};"
3275   puts $aPbxprojFile "\t\t\tname = Release;"
3276   puts $aPbxprojFile "\t\t\};\n"
3277   # End XCBuildConfiguration section
3278
3279   # Begin XCConfigurationList section
3280   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListProj) = \{"
3281   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3282   puts $aPbxprojFile "\t\tbuildConfigurations = ("
3283   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugProject) ,"
3284   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseProject) ,"
3285   puts $aPbxprojFile "\t\t\t);"
3286   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3287   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3288   puts $aPbxprojFile "\t\t\};"
3289   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListNativeTarget) = \{"
3290   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3291   puts $aPbxprojFile "\t\t\tbuildConfigurations = ("
3292   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugNativeTarget) ,"
3293   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseNativeTarget) ,"
3294   puts $aPbxprojFile "\t\t\t);"
3295   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3296   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3297   puts $aPbxprojFile "\t\t\};\n"
3298   # End XCConfigurationList section
3299
3300   puts $aPbxprojFile "\t\};"
3301   puts $aPbxprojFile "\trootObject = $aGuidsMap($aTkProjectObj) ;"
3302   puts $aPbxprojFile "\}"
3303
3304   close $aPbxprojFile
3305 }
3306
3307 proc osutils:xcdx { theOutDir theExecutable theGuidsMap } {
3308   set aUsername [exec whoami]
3309
3310   # Creating folders for Xcode project file.
3311   set anExecutableDir "${theOutDir}/${theExecutable}.xcodeproj"
3312   wokUtils:FILES:mkdir $anExecutableDir
3313   if { ! [file exists $anExecutableDir] } {
3314     puts stderr "Error: Could not create project directory \"$anExecutableDir\""
3315     return
3316   }
3317
3318   set aUserDataDir "${anExecutableDir}/xcuserdata"
3319   wokUtils:FILES:mkdir $aUserDataDir
3320   if { ! [file exists $aUserDataDir] } {
3321     puts stderr "Error: Could not create xcuserdata directorty in \"$anExecutableDir\""
3322     return
3323   }
3324
3325   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
3326   wokUtils:FILES:mkdir $aUserDataDir
3327   if { ! [file exists $aUserDataDir] } {
3328     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directorty in \"$anExecutableDir\"/xcuserdata"
3329     return
3330   }
3331
3332   set aSchemesDir "${aUserDataDir}/xcschemes"
3333   wokUtils:FILES:mkdir $aSchemesDir
3334   if { ! [file exists $aSchemesDir] } {
3335     puts stderr "Error: Could not create xcschemes directorty in \"$aUserDataDir\""
3336     return
3337   }
3338   # End folders creation.
3339
3340   # Generating GUID for tookit.
3341   upvar $theGuidsMap aGuidsMap
3342   if { ! [info exists aGuidsMap($theExecutable)] } {
3343     set aGuidsMap($theExecutable) [OS:genGUID "xcd"]
3344   }
3345
3346   # Creating xcscheme file for toolkit from template.
3347   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcode"]
3348   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theExecutable aXcschemeTmpl
3349   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theExecutable) aXcschemeTmpl
3350   set aXcschemeFile [open "$aSchemesDir/${theExecutable}.xcscheme"  "w"]
3351   puts $aXcschemeFile $aXcschemeTmpl
3352   close $aXcschemeFile
3353
3354   # Creating xcschememanagement.plist file for toolkit from template.
3355   set aPlistTmpl [osutils:readtemplate "plist" "xcode"]
3356   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theExecutable aPlistTmpl
3357   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theExecutable) aPlistTmpl
3358   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
3359   puts $aPlistFile $aPlistTmpl
3360   close $aPlistFile
3361 }
3362
3363 # Returns available Windows SDKs versions
3364 proc osutils:sdk { theSdkMajorVer {isQuietMode false} {theSdkDirectories {}} } {
3365   if { ![llength ${theSdkDirectories}] } {
3366     foreach anEnvVar { "ProgramFiles" "ProgramFiles\(x86\)" "ProgramW6432" } {
3367       if {[ info exists ::env(${anEnvVar}) ]} {
3368         lappend theSdkDirectories "$::env(${anEnvVar})/Windows Kits/${theSdkMajorVer}/Include"
3369       }
3370     }
3371   }
3372
3373   set sdk_versions {}
3374   foreach sdk_dir ${theSdkDirectories} {
3375     if { [file isdirectory ${sdk_dir}] } {
3376       lappend sdk_versions [glob -tails -directory "${sdk_dir}" -type d *]
3377     }
3378   }
3379
3380   if {![llength ${sdk_versions}] && !${isQuietMode}} {
3381     error "Error : Could not find Windows SDK ${theSdkMajorVer}"
3382   }
3383
3384   return [join [lsort -unique ${sdk_versions}] " "]
3385 }
3386
3387 # Generate global properties to Visual Studio project file for UWP solution
3388 proc osutils:uwp:proj { isUWP theProjTmpl } {
3389
3390   set uwp_properties ""
3391   set uwp_generate_metadata ""
3392   set uwp_app_container ""
3393
3394   set format_template ""
3395
3396   if { $isUWP } {
3397     set sdk_versions [osutils:sdk 10]
3398     set sdk_max_ver [lindex ${sdk_versions} end]
3399
3400     set uwp_properties "<DefaultLanguage>en-US</DefaultLanguage>\n   \
3401 <ApplicationType>Windows Store</ApplicationType>\n   \
3402 <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\n   \
3403 <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\n   \
3404 <AppContainerApplication>true</AppContainerApplication>\n   \
3405 <WindowsTargetPlatformVersion>${sdk_max_ver}</WindowsTargetPlatformVersion>\n   \
3406 <WindowsTargetPlatformMinVersion>${sdk_max_ver}</WindowsTargetPlatformMinVersion>"
3407
3408     set uwp_generate_metadata        "<GenerateWindowsMetadata>false</GenerateWindowsMetadata>"
3409
3410     regsub -all -- {[\r\n\s]*<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>} ${theProjTmpl} "" theProjTmpl
3411   } else {
3412     set format_template "\[\\r\\n\\s\]*"
3413   }
3414
3415   regsub -all -- "${format_template}__UWP_PROPERTIES__"        ${theProjTmpl} "${uwp_properties}" theProjTmpl
3416   regsub -all -- "${format_template}__UWP_GENERATE_METADATA__" ${theProjTmpl} "${uwp_generate_metadata}" theProjTmpl
3417
3418   return ${theProjTmpl}
3419 }
3420
3421 # Report all files found in package directory but not listed in FILES
3422 proc osutils:checksrcfiles { theUnit } {
3423   global path
3424   set aCasRoot [file normalize ${path}]
3425
3426   if {![file isdirectory ${aCasRoot}]} {
3427     puts "OCCT directory is not defined correctly: ${aCasRoot}"
3428     return
3429   }
3430
3431   set anUnitAbsPath [file normalize "${aCasRoot}/src/${theUnit}"]
3432
3433   if {[file exists "${anUnitAbsPath}/FILES"]} {
3434     set aFilesFile [open "${anUnitAbsPath}/FILES" rb]
3435     set aFilesFileList [split [read ${aFilesFile}] "\n"]
3436     close ${aFilesFile}
3437
3438     set aFilesFileList [lsearch -inline -all -not -exact ${aFilesFileList} ""]
3439
3440     # report all files not listed in FILES
3441     set anAllFiles [glob -tails -nocomplain -dir ${anUnitAbsPath} "*"]
3442     foreach aFile ${anAllFiles} {
3443       if { "${aFile}" == "FILES" } {
3444         continue
3445       }
3446       if { [lsearch -exact ${aFilesFileList} ${aFile}] == -1 } {
3447         puts "Warning: file ${anUnitAbsPath}/${aFile} is not listed in ${anUnitAbsPath}/FILES!"
3448       }
3449     }
3450   }
3451 }