0032433: Visualization, TKService - introduce Wasm_Window implementing Aspect_Window...
[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"
1534         }
1535       }
1536     }
1537   }
1538 }
1539
1540 # Returns string of library dependencies for generation of Visual Studio project or make lists.
1541 proc osutils:vtkCsf {{theOS ""}} {
1542   set aVtkVer "6.1"
1543
1544   set aPathSplitter ":"
1545   if {"$theOS" == "wnt"} {
1546     set aPathSplitter ";"
1547   }
1548
1549   set anOptIncs [split $::env(CSF_OPT_INC) "$aPathSplitter"]
1550   foreach anIncItem $anOptIncs {
1551     if {[regexp -- "vtk-(.*)$" [file tail $anIncItem] dummy aFoundVtkVer]} {
1552       set aVtkVer $aFoundVtkVer
1553     }
1554   }
1555
1556   set aLibArray [list vtkCommonCore vtkCommonDataModel vtkCommonExecutionModel vtkCommonMath vtkCommonTransforms vtkRenderingCore \
1557                       vtkRenderingOpenGL  vtkFiltersGeneral vtkIOCore vtkIOImage vtkImagingCore vtkInteractionStyle]
1558
1559   # Additional suffices for the libraries
1560   set anIdx 0
1561   foreach anItem $aLibArray {
1562     lset aLibArray $anIdx $anItem-$aVtkVer
1563     incr anIdx
1564   }
1565
1566   return [join $aLibArray " "]
1567 }
1568
1569 # @param theLibsList   - dependencies (libraries  list)
1570 # @param theFrameworks - dependencies (frameworks list, OS X specific)
1571 proc osutils:usedOsLibs { theToolKit theOS theLibsList theFrameworks theSrcDir { theRelease true } } {
1572   global path
1573   upvar $theLibsList   aLibsList
1574   upvar $theFrameworks aFrameworks
1575   set aLibsList   [list]
1576   set aFrameworks [list]
1577
1578   osutils:csfList $theOS aLibsMap aFrmsMap $theRelease
1579
1580   foreach aCsfElem [osutils:tk:csfInExternlib "$path/$theSrcDir/${theToolKit}/EXTERNLIB"] {
1581     if [info exists aLibsMap($aCsfElem)] {
1582       foreach aLib [split "$aLibsMap($aCsfElem)"] {
1583         if { [lsearch $aLibsList $aLib] == "-1" } {
1584           lappend aLibsList $aLib
1585         }
1586       }
1587     }
1588     if [info exists aFrmsMap($aCsfElem)] {
1589       foreach aFrm [split "$aFrmsMap($aCsfElem)"] {
1590         if { [lsearch $aFrameworks $aFrm] == "-1" } {
1591           lappend aFrameworks $aFrm
1592         }
1593       }
1594     }
1595   }
1596 }
1597
1598 # Returns liste of UD in a toolkit. tkloc is a full path wok.
1599 proc osutils:tk:units { tkloc theSrcDir } {
1600   global path
1601   set l {}
1602   set PACKAGES "$path/$theSrcDir/$tkloc/PACKAGES"
1603   foreach u [wokUtils:FILES:FileToList $PACKAGES] {
1604     if {[file isdirectory "$path/$theSrcDir/$u"]} {
1605       lappend l $u
1606     }
1607   }
1608   if { $l == {} } {
1609     ;#puts stderr "Warning. No devunit included in $tkloc"
1610   }
1611   return $l
1612 }
1613
1614 # remove from listloc OpenCascade units indesirables on NT
1615 proc osutils:juststation {goaway listloc} {
1616   global path
1617   set lret {}
1618   foreach u $listloc {
1619     if {([file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 )
1620      || (![file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 ) } {
1621       lappend lret $u
1622     }
1623   }
1624   return $lret
1625 }
1626
1627 # intersect3 - perform the intersecting of two lists, returning a list containing three lists.
1628 # The first list is everything in the first list that wasn't in the second,
1629 # the second list contains the intersection of the two lists, the third list contains everything
1630 # in the second list that wasn't in the first.
1631 proc osutils:intersect3 {list1 list2} {
1632   set la1(0) {} ; unset la1(0)
1633   set lai(0) {} ; unset lai(0)
1634   set la2(0) {} ; unset la2(0)
1635   foreach v $list1 {
1636     set la1($v) {}
1637   }
1638   foreach v $list2 {
1639     set la2($v) {}
1640   }
1641   foreach elem [concat $list1 $list2] {
1642     if {[info exists la1($elem)] && [info exists la2($elem)]} {
1643       unset la1($elem)
1644       unset la2($elem)
1645       set lai($elem) {}
1646     }
1647   }
1648   list [lsort [array names la1]] [lsort [array names lai]] [lsort [array names la2]]
1649 }
1650
1651 # Prepare relative path
1652 proc relativePath {thePathFrom thePathTo} {
1653   if { [file isdirectory "$thePathFrom"] == 0 } {
1654     return ""
1655   }
1656
1657   set aPathFrom [file normalize "$thePathFrom"]
1658   set aPathTo   [file normalize "$thePathTo"]
1659
1660   set aCutedPathFrom "${aPathFrom}/dummy"
1661   set aRelatedDeepPath ""
1662
1663   while { "$aCutedPathFrom" != [file normalize "$aCutedPathFrom/.."] } {
1664     set aCutedPathFrom [file normalize "$aCutedPathFrom/.."]
1665     # does aPathTo contain aCutedPathFrom?
1666     regsub -all $aCutedPathFrom $aPathTo "" aPathFromAfterCut
1667     if { "$aPathFromAfterCut" != "$aPathTo" } { # if so
1668       if { "$aCutedPathFrom" == "$aPathFrom" } { # just go higher, for example, ./somefolder/someotherfolder
1669         set aPathTo ".${aPathTo}"
1670       } elseif { "$aCutedPathFrom" == "$aPathTo" } { # remove the last "/"
1671         set aRelatedDeepPath [string replace $aRelatedDeepPath end end ""]
1672       }
1673       regsub -all $aCutedPathFrom $aPathTo $aRelatedDeepPath aPathToAfterCut
1674       regsub -all "//" $aPathToAfterCut "/" aPathToAfterCut
1675       return $aPathToAfterCut
1676     }
1677     set aRelatedDeepPath "$aRelatedDeepPath../"
1678
1679   }
1680
1681   return $thePathTo
1682 }
1683
1684 proc wokUtils:EASY:bs1 { s } {
1685     regsub -all {/} $s {\\} r
1686     return $r
1687 }
1688
1689 # Returns for a full path the liste of n last directory part
1690 # n = 1 => tail
1691 # n = 2 => dir/file.c
1692 # n = 3 => sdir/dir/file.c
1693 # etc..
1694 proc wokUtils:FILES:wtail { f n } {
1695     set ll [expr [llength [set lif [file split $f]]] -$n]
1696     return [join [lrange $lif $ll end] /]
1697 }
1698
1699 # Generate entry for one source file in Visual Studio 10 project file
1700 proc osutils:vcxproj:cxxfile { theFile theParams theSrcFileLevel } {
1701   if { $theParams == "" } {
1702     return "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile $theSrcFileLevel]]\" />\n"
1703   }
1704
1705   set aParams [string trim ${theParams}]
1706   append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
1707   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1708   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1709   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1710   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1711   append text "    </ClCompile>\n"
1712   return $text
1713 }
1714
1715 # Generate entry for one header file in Visual Studio 10 project file
1716 proc osutils:vcxproj:hxxfile { theFile } { return "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\" />\n" }
1717
1718 # Generate Visual Studio 2010 project filters file
1719 proc osutils:vcxproj:filters { dir proj theCxxFilesMap theHxxFilesMap } {
1720   upvar $theCxxFilesMap aCxxFilesMap
1721   upvar $theHxxFilesMap aHxxFilesMap
1722
1723   # header
1724   append text "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
1725   append text "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
1726
1727   # list of "filters" (units)
1728   append text "  <ItemGroup>\n"
1729   append text "    <Filter Include=\"Source files\">\n"
1730   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1731   append text "    </Filter>\n"
1732   append text "    <Filter Include=\"Header files\">\n"
1733   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1734   append text "    </Filter>\n"
1735   foreach unit $aCxxFilesMap(units) {
1736     append text "    <Filter Include=\"Source files\\${unit}\">\n"
1737     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1738     append text "    </Filter>\n"
1739   }
1740   foreach unit $aHxxFilesMap(units) {
1741     append text "    <Filter Include=\"Header files\\${unit}\">\n"
1742     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1743     append text "    </Filter>\n"
1744   }
1745   append text "  </ItemGroup>\n"
1746
1747   # list of cxx files
1748   append text "  <ItemGroup>\n"
1749   foreach unit $aCxxFilesMap(units) {
1750     foreach file $aCxxFilesMap($unit) {
1751       append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1752       append text "      <Filter>Source files\\${unit}</Filter>\n"
1753       append text "    </ClCompile>\n"
1754     }
1755   }
1756   append text "  </ItemGroup>\n"
1757
1758   # list of hxx files
1759   append text "  <ItemGroup>\n"
1760   foreach unit $aHxxFilesMap(units) {
1761     foreach file $aHxxFilesMap($unit) {
1762       append text "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1763       append text "      <Filter>Header files\\${unit}</Filter>\n"
1764       append text "    </ClInclude>\n"
1765     }
1766   }
1767   append text "  </ItemGroup>\n"
1768
1769   append text "  <ItemGroup>\n"
1770   append text "    <ResourceCompile Include=\"${proj}.rc\" />\n"
1771   append text "  </ItemGroup>\n"
1772
1773   # end
1774   append text "</Project>"
1775
1776   # write file
1777   set fp [open [set fvcproj [file join $dir ${proj}.vcxproj.filters]] w]
1778   fconfigure $fp -translation crlf
1779   puts $fp $text
1780   close $fp
1781
1782   return ${proj}.vcxproj.filters
1783 }
1784
1785 # Generate RC file content for ToolKit from template
1786 proc osutils:readtemplate:rc {theOutDir theToolKit} {
1787   set aLoc "$::THE_CASROOT/adm/templates/template_dll.rc"
1788   set aBody [wokUtils:FILES:FileToString $aLoc]
1789   regsub -all -- {__TKNAM__} $aBody $theToolKit aBody
1790
1791   set aFile [open "${theOutDir}/${theToolKit}.rc" "w"]
1792   fconfigure $aFile -translation lf
1793   puts $aFile $aBody
1794   close $aFile
1795   return "${theOutDir}/${theToolKit}.rc"
1796 }
1797
1798 # Generate Visual Studio project file for ToolKit
1799 proc osutils:vcproj { theVcVer isUWP theOutDir theToolKit theGuidsMap theSrcDir theSourceDirOther } {
1800   global path
1801
1802   set aHasQtDep "false"
1803   set aTkDefines ""
1804   foreach aCsfElem [osutils:tk:csfInExternlib "$path/$theSrcDir/${theToolKit}/EXTERNLIB"] {
1805     if { "$aCsfElem" == "CSF_QT" } {
1806       set aHasQtDep "true"
1807     } elseif { "$aCsfElem" == "CSF_OpenGlLibs" } {
1808       set aTkDefines "$aTkDefines;HAVE_OPENGL"
1809     } elseif { "$aCsfElem" == "CSF_OpenGlesLibs" } {
1810       set aTkDefines "$aTkDefines;HAVE_GLES2"
1811     }
1812   }
1813   set theProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 0]
1814
1815   set l_compilable [osutils:compilable wnt]
1816   regsub -all -- {__TKNAM__} $theProjTmpl $theToolKit theProjTmpl
1817
1818   upvar $theGuidsMap aGuidsMap
1819   if { ! [info exists aGuidsMap($theToolKit)] } {
1820     set aGuidsMap($theToolKit) [OS:genGUID]
1821   }
1822   regsub -all -- {__PROJECT_GUID__} $theProjTmpl $aGuidsMap($theToolKit) theProjTmpl
1823
1824   set theProjTmpl [osutils:uwp:proj $isUWP ${theProjTmpl}]
1825
1826   set aUsedLibs [list]
1827
1828   if { $isUWP } {
1829     lappend aUsedLibs "WindowsApp.lib"
1830   }
1831
1832   foreach tkx [osutils:commonUsedTK  $theToolKit $theSrcDir $theSourceDirOther] {
1833     lappend aUsedLibs "${tkx}.lib"
1834   }
1835
1836   set anOsReleaseLibs {}
1837   set anOsDebugLibs {}
1838   osutils:usedOsLibs $theToolKit "wnt" anOsReleaseLibs aFrameworks $theSrcDir true
1839   osutils:usedOsLibs $theToolKit "wnt" anOsDebugLibs aFrameworks $theSrcDir false
1840
1841   # correct names of referred third-party libraries that are named with suffix
1842   # depending on VC version
1843   regsub -all -- {__TKDEP__} $theProjTmpl [osutils:depLibraries $aUsedLibs $anOsReleaseLibs $theVcVer] theProjTmpl
1844   regsub -all -- {__TKDEP_DEBUG__} $theProjTmpl [osutils:depLibraries $aUsedLibs $anOsDebugLibs $theVcVer] theProjTmpl
1845   regsub -all -- {__TKDEFINES__} $theProjTmpl $aTkDefines theProjTmpl
1846
1847   set anIncPaths "..\\..\\..\\inc"
1848   set aFilesSection ""
1849   set aVcFilesCxx(units) ""
1850   set aVcFilesHxx(units) ""
1851   set listloc [osutils:tk:units $theToolKit $theSrcDir]
1852   if [array exists written] { unset written }
1853   #puts "\t1 [wokparam -v %CMPLRS_CXX_Options [w_info -f]] father"
1854   #puts "\t2 [wokparam -v %CMPLRS_CXX_Options] branch"
1855   #puts "\t1 [wokparam -v %CMPLRS_C_Options [w_info -f]] father"
1856   #puts "\t2 [wokparam -v %CMPLRS_C_Options] branch"
1857   set fxloparamfcxx [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx f] [_get_options wnt cmplrs_cxx b]] 2]
1858   set fxloparamfc   [lindex [osutils:intersect3 [_get_options wnt cmplrs_c f] [_get_options wnt cmplrs_c b]] 2]
1859   set fxloparam ""
1860   foreach fxlo $listloc {
1861     set xlo $fxlo
1862     set aSrcFiles [osutils:tk:cxxfiles $xlo wnt $theSrcDir]
1863     set aHxxFiles [osutils:tk:hxxfiles $xlo wnt $theSrcDir]
1864
1865     # prepare Qt moc files, appears only in Inspector - directory tools
1866     set aGeneratedFiles {}
1867     if { "$aHasQtDep" == "true" } {
1868       set aMocResFiles [osutils:tk:mocfiles $aHxxFiles $theOutDir]
1869       set aGeneratedFiles [osutils:tk:execfiles $aMocResFiles $theOutDir moc${::SYS_EXE_SUFFIX} moc cpp]
1870
1871       set aQrcResFiles [osutils:tk:qrcfiles $xlo wnt $theSrcDir]
1872       set aQrcFiles [osutils:tk:execfiles $aQrcResFiles $theOutDir rcc${::SYS_EXE_SUFFIX} rcc cpp]
1873       foreach resFile $aQrcFiles {
1874         lappend aGeneratedFiles $resFile
1875       }
1876     }
1877
1878     set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx $fxlo]
1879     if {$fxlo_cmplrs_options_cxx == ""} {
1880       set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx b]
1881     }
1882         set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c $fxlo]
1883     if {$fxlo_cmplrs_options_c == ""} {
1884       set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c b]
1885     }
1886     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx b] $fxlo_cmplrs_options_cxx] 2]"
1887     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_c b] $fxlo_cmplrs_options_c] 2]"
1888         #puts "\t3 [wokparam -v %CMPLRS_CXX_Options] branch CXX "
1889         #puts "\t4 [wokparam -v %CMPLRS_CXX_Options $fxlo] $fxlo  CXX"
1890         #puts "\t5 [wokparam -v %CMPLRS_C_Options] branch C"
1891         #puts "\t6 [wokparam -v %CMPLRS_C_Options   $fxlo] $fxlo  C"
1892     set needparam ""
1893     foreach partopt $fxloparam {
1894       if {[string first "-I" $partopt] == "0"} {
1895         # this is an additional includes search path
1896         continue
1897       }
1898       set needparam "$needparam $partopt"
1899     }
1900
1901     # Format of projects in vc10+ is different from vc7-9
1902     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1903       foreach aSrcFile [lsort $aSrcFiles] {
1904         if { ![info exists written([file tail $aSrcFile])] } {
1905           set written([file tail $aSrcFile]) 1
1906           append aFilesSection [osutils:vcxproj:cxxfile $aSrcFile $needparam 3]
1907         } else {
1908           puts "Warning : in vcproj more than one occurrences for [file tail $aSrcFile]"
1909         }
1910         if { ! [info exists aVcFilesCxx($xlo)] } { lappend aVcFilesCxx(units) $xlo }
1911         lappend aVcFilesCxx($xlo) $aSrcFile
1912       }
1913       foreach aHxxFile [lsort $aHxxFiles] {
1914         if { ![info exists written([file tail $aHxxFile])] } {
1915           set written([file tail $aHxxFile]) 1
1916           append aFilesSection [osutils:vcxproj:hxxfile $aHxxFile]
1917         } else {
1918           puts "Warning : in vcproj more than one occurrences for [file tail $aHxxFile]"
1919         }
1920         if { ! [info exists aVcFilesHxx($xlo)] } { lappend aVcFilesHxx(units) $xlo }
1921         lappend aVcFilesHxx($xlo) $aHxxFile
1922       }
1923       foreach aGenFile [lsort $aGeneratedFiles] {
1924         if { ![info exists written([file tail $aGenFile])] } {
1925           set written([file tail $aGenFile]) 1
1926           append aFilesSection [osutils:vcxproj:cxxfile $aGenFile $needparam 5]
1927         } else {
1928           puts "Warning : in vcproj more than one occurrences for [file tail $aGenFile]"
1929         }
1930         if { ! [info exists aVcFilesCxx($xlo)] } { lappend aVcFilesCxx(units) $xlo }
1931         lappend aVcFilesCxx($xlo) $aGenFile
1932       }
1933     } else {
1934       append aFilesSection "\t\t\t<Filter\n"
1935       append aFilesSection "\t\t\t\tName=\"${xlo}\"\n"
1936       append aFilesSection "\t\t\t\t>\n"
1937       foreach aSrcFile [lsort $aSrcFiles] {
1938         if { ![info exists written([file tail $aSrcFile])] } {
1939           set written([file tail $aSrcFile]) 1
1940           append aFilesSection [osutils:vcproj:file $theVcVer $aSrcFile $needparam]
1941         } else {
1942           puts "Warning : in vcproj more than one occurrences for [file tail $aSrcFile]"
1943         }
1944       }
1945       append aFilesSection "\t\t\t</Filter>\n"
1946     }
1947   }
1948
1949   regsub -all -- {__TKINC__}  $theProjTmpl $anIncPaths theProjTmpl
1950   regsub -all -- {__FILES__}  $theProjTmpl $aFilesSection theProjTmpl
1951
1952   # write file
1953   set aFile [open [set aVcFiles [file join $theOutDir ${theToolKit}.[osutils:vcproj:ext $theVcVer]]] w]
1954   fconfigure $aFile -translation crlf
1955   puts $aFile $theProjTmpl
1956   close $aFile
1957
1958   # write filters file for vc10+
1959   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1960     lappend aVcFiles [osutils:vcxproj:filters $theOutDir $theToolKit aVcFilesCxx aVcFilesHxx]
1961   }
1962
1963   # write resource file
1964   lappend aVcFiles [osutils:readtemplate:rc $theOutDir $theToolKit]
1965
1966   return $aVcFiles
1967 }
1968
1969 # Appends OS libraries into the list of used libraries.
1970 # Corrects list of referred third-party libraries that are named with suffix
1971 # depending on VC version
1972 # Unites list of used libraries into a variable with separator for VStudio older than vc9
1973 # @param theUsedLibs List of libraries, to be changed
1974 # @param theOsLibs List of Os library names, before using an extension should be added
1975 # @param theVcVer version of VStudio
1976
1977 proc osutils:depLibraries { theUsedLibs theOsLibs theVcVer } {
1978   foreach aLibIter $theOsLibs {
1979     lappend theUsedLibs "${aLibIter}.${::SYS_LIB_SUFFIX}"
1980   }
1981
1982   # correct names of referred third-party libraries that are named with suffix
1983   # depending on VC version
1984   set aVCRTVer [string range $theVcVer 0 3]
1985   regsub -all -- {vc[0-9]+} $theUsedLibs $aVCRTVer theUsedLibs
1986
1987   # and put this list to project file
1988   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1989     set theUsedLibs [join $theUsedLibs {;}]
1990   }
1991
1992   return $theUsedLibs
1993 }
1994
1995 # for a unit returns a map containing all its file in the current
1996 # workbench
1997 # local = 1 only local files
1998 proc osutils:tk:loadunit { loc map theSrcDir} {
1999   #puts $loc
2000   upvar $map TLOC
2001   catch { unset TLOC }
2002   set lfiles [_get_used_files $loc $theSrcDir]
2003   foreach f $lfiles {
2004     #puts "\t$f"
2005     set t [lindex $f 0]
2006     set p [lindex $f 2]
2007     if [info exists TLOC($t)] {
2008       set l $TLOC($t)
2009       lappend l $p
2010       set TLOC($t) $l
2011     } else {
2012       set TLOC($t) $p
2013     }
2014   }
2015   return
2016 }
2017
2018 # Returns the list of all files name in a toolkit within specified list of file extensions.
2019 proc osutils:tk:files { tkloc theExtensions theSrcDir } {
2020   set Tfiles(source,nocdlpack)     {source pubinclude}
2021   set Tfiles(source,toolkit)       {}
2022   set Tfiles(source,executable)    {source pubinclude}
2023   set listloc [concat [osutils:tk:units $tkloc $theSrcDir] $tkloc ]
2024   #puts " listloc = $listloc"
2025
2026   set resultloc $listloc
2027   set lret {}
2028   foreach loc $resultloc {
2029     set utyp [_get_type $loc]
2030     #puts "\"$utyp\" \"$loc\""
2031     switch $utyp {
2032          "t" { set utyp "toolkit" }
2033          "n" { set utyp "nocdlpack" }
2034          "x" { set utyp "executable" }
2035          default { error "Error: Cannot determine type of unit $loc, check adm/UDLIST!" }
2036     }
2037     if [array exists map] { unset map }
2038     osutils:tk:loadunit $loc map $theSrcDir
2039     #puts " loc = $loc === > [array names map]"
2040     set LType $Tfiles(source,${utyp})
2041     foreach typ [array names map] {
2042       if { [lsearch $LType $typ] == -1 } {
2043         unset map($typ)
2044       }
2045     }
2046     foreach type [array names map] {
2047       #puts $type
2048       foreach f $map($type) {
2049         #puts $f
2050         if { [lsearch $theExtensions [file extension $f]] != -1 } {
2051           lappend lret $f
2052         }
2053       }
2054     }
2055   }
2056   return $lret
2057 }
2058
2059 # Returns the list of all compilable files name in a toolkit.
2060 proc osutils:tk:cxxfiles { tkloc thePlatform theSrcDir } { return [osutils:tk:files $tkloc [osutils:compilable $thePlatform] $theSrcDir] }
2061
2062 # Returns the list of all header files name in a toolkit.
2063 proc osutils:tk:hxxfiles { tkloc thePlatform theSrcDir } { return [osutils:tk:files $tkloc [osutils:fileExtensionsHeaders $thePlatform] $theSrcDir] }
2064
2065 # Returns the list of all resource (qrc) files name in a toolkit.
2066 proc osutils:tk:qrcfiles { tkloc thePlatform theSourceDir } { return [osutils:tk:files $tkloc [osutils:fileExtensionsResources $thePlatform] $theSourceDir] }
2067
2068 # Returns the list of all header files name in a toolkit.
2069 proc osutils:tk:mocfiles { HxxFiles theOutDir } {
2070   set lret {}
2071   foreach file $HxxFiles {
2072     # processing only files where Q_OBJECT exists
2073     set fd [open "$file" rb]
2074     set FILES [split [read $fd] "\n"]
2075     close $fd
2076
2077     set isQObject [expr [regexp "Q_OBJECT" $FILES]]
2078     if { ! $isQObject } {
2079       continue;
2080     }
2081     lappend lret $file
2082   }
2083   return $lret
2084 }
2085
2086 # Returns the list of all header files name in a toolkit.
2087 proc osutils:tk:execfiles { theFiles theOutDir theCommand thePrefix theExtension} {
2088   set lret {}
2089   set anOutDir $theOutDir/$thePrefix
2090   file mkdir $anOutDir
2091
2092   foreach file $theFiles {
2093     set aResourceName [file tail $file]
2094     set anOutFile $anOutDir/${thePrefix}_[file rootname $aResourceName].$theExtension
2095
2096     exec $theCommand $file -o $anOutFile
2097     lappend lret $anOutFile
2098   }
2099   return $lret
2100 }
2101
2102 # Generate Visual Studio project file for executable
2103 proc osutils:vcprojx { theVcVer isUWP theOutDir theToolKit theGuidsMap theSrcDir theSourceDirOther } {
2104   set aVcFiles {}
2105   foreach f [osutils:tk:cxxfiles $theToolKit wnt $theSrcDir] {
2106     set aProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 1]
2107
2108     set aProjName [file rootname [file tail $f]]
2109     set l_compilable [osutils:compilable wnt]
2110     regsub -all -- {__XQTNAM__} $aProjTmpl $aProjName aProjTmpl
2111
2112     upvar $theGuidsMap aGuidsMap
2113     if { ! [info exists aGuidsMap($aProjName)] } {
2114       set aGuidsMap($aProjName) [OS:genGUID]
2115     }
2116     regsub -all -- {__PROJECT_GUID__} $aProjTmpl $aGuidsMap($aProjName) aProjTmpl
2117
2118     set aUsedLibs [list]
2119     foreach tkx [osutils:commonUsedTK  $theToolKit $theSrcDir $theSourceDirOther] {
2120       lappend aUsedLibs "${tkx}.lib"
2121     }
2122
2123     set anOsReleaseLibs {}
2124     set anOsDebugLibs {}
2125     osutils:usedOsLibs $theToolKit "wnt" anOsReleaseLibs aFrameworks $theSrcDir true
2126     osutils:usedOsLibs $theToolKit "wnt" anOsDebugLibs aFrameworks $theSrcDir false
2127
2128     set aVCRTVer [string range $theVcVer 0 3]
2129     regsub -all -- {__TKDEP__} $aProjTmpl [osutils:depLibraries $aUsedLibs $anOsReleaseLibs $theVcVer] aProjTmpl
2130     regsub -all -- {__TKDEP_DEBUG__} $aProjTmpl [osutils:depLibraries $aUsedLibs $anOsDebugLibs $theVcVer] aProjTmpl
2131     regsub -all -- {__TKDEFINES__} $aProjTmpl "" aProjTmpl
2132
2133     set aFilesSection ""
2134     set aVcFilesCxx(units) ""
2135         set aVcFilesHxx(units) ""
2136
2137     if { ![info exists written([file tail $f])] } {
2138       set written([file tail $f]) 1
2139
2140       if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
2141         append aFilesSection [osutils:vcxproj:cxxfile $f "" 3]
2142         if { ! [info exists aVcFilesCxx($theToolKit)] } { lappend aVcFilesCxx(units) $theToolKit }
2143         lappend aVcFilesCxx($theToolKit) $f
2144       } else {
2145         append aFilesSection "\t\t\t<Filter\n"
2146         append aFilesSection "\t\t\t\tName=\"$theToolKit\"\n"
2147         append aFilesSection "\t\t\t\t>\n"
2148         append aFilesSection [osutils:vcproj:file $theVcVer $f ""]
2149         append aFilesSection "\t\t\t</Filter>"
2150       }
2151     } else {
2152       puts "Warning : in vcproj there are more than one occurrences for [file tail $f]"
2153     }
2154     #puts "$aProjTmpl $aFilesSection"
2155     set anIncPaths "..\\..\\..\\inc"
2156     regsub -all -- {__TKINC__}  $aProjTmpl $anIncPaths    aProjTmpl
2157     regsub -all -- {__FILES__}  $aProjTmpl $aFilesSection aProjTmpl
2158     regsub -all -- {__CONF__}   $aProjTmpl Application    aProjTmpl
2159
2160     regsub -all -- {__XQTEXT__} $aProjTmpl "exe" aProjTmpl
2161
2162     set aFile [open [set aVcFilePath [file join $theOutDir ${aProjName}.[osutils:vcproj:ext $theVcVer]]] w]
2163     fconfigure $aFile -translation crlf
2164     puts $aFile $aProjTmpl
2165     close $aFile
2166
2167     set aCommonSettingsFile "$aVcFilePath.user"
2168     lappend aVcFiles $aVcFilePath
2169
2170     # write filters file for vc10
2171     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
2172       lappend aVcFiles [osutils:vcxproj:filters $theOutDir $aProjName aVcFilesCxx aVcFilesHxx]
2173     }
2174
2175     # write resource file
2176     lappend aVcFiles [osutils:readtemplate:rc $theOutDir $aProjName]
2177
2178     set aCommonSettingsFileTmpl ""
2179     if { "$theVcVer" == "vc7" || "$theVcVer" == "vc8" } {
2180       # nothing
2181     } elseif { "$theVcVer" == "vc9" } {
2182       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcproj.user.vc9x"]
2183     } else {
2184       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcxproj.user.vc10x"]
2185     }
2186     if { "$aCommonSettingsFileTmpl" != "" } {
2187       regsub -all -- {__VCVER__} $aCommonSettingsFileTmpl $aVCRTVer aCommonSettingsFileTmpl
2188
2189       set aFile [open [set aVcFilePath "$aCommonSettingsFile"] w]
2190       fconfigure $aFile -translation crlf
2191       puts $aFile $aCommonSettingsFileTmpl
2192       close $aFile
2193
2194       lappend aVcFiles "$aCommonSettingsFile"
2195     }
2196   }
2197   return $aVcFiles
2198 }
2199
2200 # Generate entry for one source file in Visual Studio 7 - 9 project file
2201 proc osutils:vcproj:file { theVcVer theFile theOptions } {
2202   append aText "\t\t\t\t<File\n"
2203   append aText "\t\t\t\t\tRelativePath=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
2204   if { $theOptions == "" } {
2205     append aText "\t\t\t\t</File>\n"
2206     return $aText
2207   }
2208
2209   append aText "\t\t\t\t\t<FileConfiguration\n"
2210   append aText "\t\t\t\t\t\tName=\"Release\|Win32\">\n"
2211   append aText "\t\t\t\t\t\t<Tool\n"
2212   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2213   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2214   foreach aParam $theOptions {
2215     append aText "$aParam "
2216   }
2217   append aText "\"\n"
2218   append aText "\t\t\t\t\t\t/>\n"
2219   append aText "\t\t\t\t\t</FileConfiguration>\n"
2220
2221   append aText "\t\t\t\t\t<FileConfiguration\n"
2222   append aText "\t\t\t\t\t\tName=\"Debug\|Win32\">\n"
2223   append aText "\t\t\t\t\t\t<Tool\n"
2224   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2225   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2226   foreach aParam $theOptions {
2227     append aText "$aParam "
2228   }
2229   append aText "\"\n"
2230   append aText "\t\t\t\t\t\t/>\n"
2231   append aText "\t\t\t\t\t</FileConfiguration>\n"
2232   if { "$theVcVer" == "vc7" } {
2233     append aText "\t\t\t\t</File>\n"
2234     return $aText
2235   }
2236
2237   append aText "\t\t\t\t\t<FileConfiguration\n"
2238   append aText "\t\t\t\t\t\tName=\"Release\|x64\">\n"
2239   append aText "\t\t\t\t\t\t<Tool\n"
2240   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2241   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2242   foreach aParam $theOptions {
2243     append aText "$aParam "
2244   }
2245   append aText "\"\n"
2246   append aText "\t\t\t\t\t\t/>\n"
2247   append aText "\t\t\t\t\t</FileConfiguration>\n"
2248
2249   append aText "\t\t\t\t\t<FileConfiguration\n"
2250   append aText "\t\t\t\t\t\tName=\"Debug\|x64\">\n"
2251   append aText "\t\t\t\t\t\t<Tool\n"
2252   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2253   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2254   foreach aParam $theOptions {
2255     append aText "$aParam "
2256   }
2257   append aText "\"\n"
2258   append aText "\t\t\t\t\t\t/>\n"
2259   append aText "\t\t\t\t\t</FileConfiguration>\n"
2260
2261   append aText "\t\t\t\t</File>\n"
2262   return $aText
2263 }
2264
2265 proc wokUtils:FILES:mkdir { d } {
2266     global tcl_version
2267     regsub -all {\.[^.]*} $tcl_version "" major
2268     if { $major == 8 } {
2269         file mkdir $d
2270     } else {
2271         if ![file exists $d] {
2272             if { "[info command mkdir]" == "mkdir" } {
2273                 mkdir -path $d
2274             } else {
2275                 puts stderr "wokUtils:FILES:mkdir : Error unable to find a mkdir command."
2276             }
2277         }
2278     }
2279     if [file exists $d] {
2280         return $d
2281     } else {
2282         return {}
2283     }
2284 }
2285
2286 ####### CODEBLOCK ###################################################################
2287 # Function to generate Code Blocks workspace and project files
2288 proc OS:MKCBP { theOutDir theModules theAllSolution thePlatform theCmpl } {
2289   puts stderr "Generating project files for Code Blocks"
2290
2291   # Generate projects for toolkits and separate workspace for each module
2292   foreach aModule $theModules {
2293     OS:cworkspace          $aModule $aModule $theOutDir
2294     OS:cbp        $theCmpl $aModule          $theOutDir $thePlatform
2295   }
2296
2297   # Generate single workspace "OCCT" containing projects from all modules
2298   if { "$theAllSolution" != "" } {
2299     OS:cworkspace $theAllSolution $theModules $theOutDir
2300   }
2301
2302   puts "The Code Blocks workspace and project files are stored in the $theOutDir directory"
2303 }
2304
2305 # Generate Code Blocks projects
2306 proc OS:cbp { theCmpl theModules theOutDir thePlatform } {
2307   set aProjectFiles {}
2308   foreach aModule $theModules {
2309     foreach aToolKit [${aModule}:toolkits] {
2310       lappend aProjectFiles [osutils:cbptk $theCmpl $theOutDir $aToolKit $thePlatform]
2311     }
2312     foreach anExecutable [OS:executable ${aModule}] {
2313       lappend aProjectFiles [osutils:cbpx  $theCmpl $theOutDir $anExecutable $thePlatform]
2314     }
2315   }
2316   return $aProjectFiles
2317 }
2318
2319 # Generate Code::Blocks project file for ToolKit
2320 proc osutils:cbptk { theCmpl theOutDir theToolKit thePlatform} {
2321   set aUsedLibs     [list]
2322   set aFrameworks   [list]
2323   set anIncPaths    [list]
2324   set aTKDefines    [list]
2325   set aTKSrcFiles   [list]
2326
2327   # collect list of referred libraries to link with
2328   osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks "src"
2329   set aDepToolkits [wokUtils:LIST:Purge [osutils:tk:close $theToolKit "src" ""]]
2330   foreach tkx $aDepToolkits {
2331     lappend aUsedLibs "${tkx}"
2332   }
2333
2334   lappend anIncPaths "../../../inc"
2335   set listloc [osutils:tk:units $theToolKit "src"]
2336
2337   if { [llength $listloc] == 0 } {
2338     set listloc $theToolKit
2339   }
2340
2341   if [array exists written] { unset written }
2342   foreach fxlo $listloc {
2343     set xlo       $fxlo
2344     set aSrcFiles [osutils:tk:cxxfiles $xlo $thePlatform "src"]
2345     foreach aSrcFile [lsort $aSrcFiles] {
2346       if { ![info exists written([file tail $aSrcFile])] } {
2347         set written([file tail $aSrcFile]) 1
2348         lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2349       } else {
2350         puts "Warning : more than one occurrences for [file tail $aSrcFile]"
2351       }
2352     }
2353
2354     # macros for correct DLL exports
2355 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2356 #      lappend aTKDefines "__${xlo}_DLL"
2357 #    }
2358   }
2359
2360   return [osutils:cbp $theCmpl $theOutDir $theToolKit $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines]
2361 }
2362
2363 # Generates Code Blocks workspace.
2364 proc OS:cworkspace { theSolName theModules theOutDir } {
2365   global path
2366   set aWsFilePath "${theOutDir}/${theSolName}.workspace"
2367   set aFile [open $aWsFilePath "w"]
2368   set isActiveSet 0
2369   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2370   puts $aFile "<CodeBlocks_workspace_file>"
2371   puts $aFile "\t<Workspace title=\"${theSolName}\">"
2372
2373   # collect list of projects to be created
2374   foreach aModule $theModules {
2375     # toolkits
2376     foreach aToolKit [osutils:tk:sort [${aModule}:toolkits] "src" ""] {
2377       set aDependencies [LibToLink $aToolKit "src" ""]
2378       if { [llength $aDependencies] == 0 } {
2379         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" />"
2380       } else {
2381         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" >"
2382         foreach aDepTk $aDependencies {
2383           puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2384         }
2385         puts $aFile "\t\t</Project>"
2386       }
2387     }
2388
2389     # executables, assume one project per cxx file...
2390     foreach aUnit [OS:executable ${aModule}] {
2391       set aUnitLoc $aUnit
2392       set src_files [_get_used_files $aUnit "src" false]
2393       set aSrcFiles {}
2394       foreach s $src_files { 
2395         regexp {source ([^\s]+)} $s dummy name
2396         lappend aSrcFiles $name
2397       }
2398       foreach aSrcFile $aSrcFiles {
2399         set aFileExtension [file extension $aSrcFile]
2400         if { $aFileExtension == ".cxx" } {
2401           set aPrjName [file rootname $aSrcFile]
2402           set aDependencies [list]
2403           if {[file isdirectory $path/src/$aUnitLoc]} {
2404             set aDependencies [LibToLinkX $aUnitLoc [file rootname $aSrcFile] "src" ""]
2405           }
2406           set anActiveState ""
2407           if { $isActiveSet == 0 } {
2408             set anActiveState " active=\"1\""
2409             set isActiveSet 1
2410           }
2411           if { [llength $aDependencies] == 0 } {
2412             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}/>"
2413           } else {
2414             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}>"
2415             foreach aDepTk $aDependencies {
2416               puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2417             }
2418             puts $aFile "\t\t</Project>"
2419           }
2420         }
2421       }
2422     }
2423   }
2424
2425   puts $aFile "\t</Workspace>"
2426   puts $aFile "</CodeBlocks_workspace_file>"
2427   close $aFile
2428
2429   return $aWsFilePath
2430 }
2431
2432 # Generate Code::Blocks project file for Executable
2433 proc osutils:cbpx { theCmpl theOutDir theToolKit thePlatform } {
2434   global path
2435   set aWokArch    "$::env(ARCH)"
2436
2437   set aCbpFiles {}
2438   foreach aSrcFile [osutils:tk:cxxfiles $theToolKit $thePlatform "src"] {
2439     # collect list of referred libraries to link with
2440     set aUsedLibs     [list]
2441     set aFrameworks   [list]
2442     set anIncPaths    [list]
2443     set aTKDefines    [list]
2444     set aTKSrcFiles   [list]
2445     set aProjName [file rootname [file tail $aSrcFile]]
2446
2447     osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks "src"
2448
2449     set aDepToolkits [LibToLinkX $theToolKit $aProjName "src" ""]
2450     foreach tkx $aDepToolkits {
2451       if {[_get_type $tkx] == "t"} {
2452         lappend aUsedLibs "${tkx}"
2453       }
2454       if {[lsearch [glob -tails -directory "$path/src" -types d *] $tkx] == "-1"} {
2455         lappend aUsedLibs "${tkx}"
2456       }
2457     }
2458
2459     set WOKSteps_exec_link [_get_options lin WOKSteps_exec_link $theToolKit]
2460     if { [regexp {WOKStep_DLLink} $WOKSteps_exec_link] || [regexp {WOKStep_Libink} $WOKSteps_exec_link] } {
2461       set isExecutable "false"
2462     } else {
2463       set isExecutable "true"
2464     }
2465
2466     if { ![info exists written([file tail $aSrcFile])] } {
2467       set written([file tail $aSrcFile]) 1
2468       lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2469     } else {
2470       puts "Warning : in cbp there are more than one occurrences for [file tail $aSrcFile]"
2471     }
2472
2473     # macros for correct DLL exports
2474 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2475 #      lappend aTKDefines "__${theToolKit}_DLL"
2476 #    }
2477
2478     # common include paths
2479     lappend anIncPaths "../../../inc"
2480
2481     lappend aCbpFiles [osutils:cbp $theCmpl $theOutDir $aProjName $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines $isExecutable]
2482   }
2483
2484   return $aCbpFiles
2485 }
2486
2487 # This function intended to generate Code::Blocks project file
2488 # @param theCmpl       - the compiler (gcc or msvc)
2489 # @param theOutDir     - output directory to place project file
2490 # @param theProjName   - project name
2491 # @param theSrcFiles   - list of source files
2492 # @param theLibsList   - dependencies (libraries  list)
2493 # @param theFrameworks - dependencies (frameworks list, Mac OS X specific)
2494 # @param theIncPaths   - header search paths
2495 # @param theDefines    - compiler macro definitions
2496 # @param theIsExe      - flag to indicate executable / library target
2497 proc osutils:cbp { theCmpl theOutDir theProjName thePlatform theSrcFiles theLibsList theFrameworks theIncPaths theDefines {theIsExe "false"} } {
2498   set aWokArch    "$::env(ARCH)"
2499
2500   set aCmplCbp "gcc"
2501   set aCmplFlags        [list]
2502   set aCmplFlagsRelease [list]
2503   set aCmplFlagsDebug   [list]
2504   set toPassArgsByFile 0
2505   set aLibPrefix "lib"
2506   set aPlatformAndCompiler "${thePlatform}/gcc"
2507   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } {
2508     set aPlatformAndCompiler "${thePlatform}/clang"
2509   }
2510   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" || "$thePlatform" == "qnx" } {
2511     set toPassArgsByFile 1
2512   }
2513   if { "$theCmpl" == "msvc" } {
2514     set aCmplCbp "msvc8"
2515     set aLibPrefix ""
2516   }
2517
2518   if { "$theCmpl" == "msvc" } {
2519     set aCmplFlags        "-arch:SSE2 -EHsc -W4 -MP"
2520     set aCmplFlagsRelease "-MD  -O2"
2521     set aCmplFlagsDebug   "-MDd -Od -Zi"
2522     lappend aCmplFlags    "-D_CRT_SECURE_NO_WARNINGS"
2523     lappend aCmplFlags    "-D_CRT_NONSTDC_NO_DEPRECATE"
2524   } elseif { "$theCmpl" == "gcc" } {
2525     if { "$thePlatform" != "qnx" } {
2526       set aCmplFlags      "-mmmx -msse -msse2 -mfpmath=sse"
2527     }
2528     set aCmplFlagsRelease "-O2"
2529     set aCmplFlagsDebug   "-O0 -g"
2530     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2531       lappend aCmplFlags "-std=gnu++0x"
2532       lappend aCmplFlags "-D_WIN32_WINNT=0x0501"
2533     } else {
2534       lappend aCmplFlags "-std=c++0x"
2535       lappend aCmplFlags "-fPIC"
2536       lappend aCmplFlags "-DOCC_CONVERT_SIGNALS"
2537     }
2538     lappend aCmplFlags   "-Wall"
2539     lappend aCmplFlags   "-Wextra"
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 }