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