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