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