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