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