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