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