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