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