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