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