0032323: Configuration - drop unused dependency from Xmu
[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   "-fexceptions"
2540   }
2541   lappend aCmplFlagsRelease "-DNDEBUG"
2542   lappend aCmplFlagsRelease "-DNo_Exception"
2543   lappend aCmplFlagsDebug   "-D_DEBUG"
2544   if { "$thePlatform" == "qnx" } {
2545     lappend aCmplFlags "-D_QNX_SOURCE"
2546   }
2547
2548   set aCbpFilePath    "${theOutDir}/${theProjName}.cbp"
2549   set aLnkFileName    "${theProjName}_obj.link"
2550   set aLnkDebFileName "${theProjName}_objd.link"
2551   set aLnkFilePath    "${theOutDir}/${aLnkFileName}"
2552   set aLnkDebFilePath "${theOutDir}/${aLnkDebFileName}"
2553   set aFile [open $aCbpFilePath "w"]
2554   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2555   puts $aFile "<CodeBlocks_project_file>"
2556   puts $aFile "\t<FileVersion major=\"1\" minor=\"6\" />"
2557   puts $aFile "\t<Project>"
2558   puts $aFile "\t\t<Option title=\"$theProjName\" />"
2559   puts $aFile "\t\t<Option pch_mode=\"2\" />"
2560   puts $aFile "\t\t<Option compiler=\"$aCmplCbp\" />"
2561   puts $aFile "\t\t<Build>"
2562
2563   # Release target configuration
2564   puts $aFile "\t\t\t<Target title=\"Release\">"
2565   if { "$theIsExe" == "true" } {
2566     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bin/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2567     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2568   } else {
2569     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2570       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\" />"
2571     } else {
2572       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/lib/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2573     }
2574     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2575   }
2576   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/obj\" />"
2577   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2578   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2579   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2580     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2581   } else {
2582     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2583   }
2584
2585   # compiler options per TARGET (including defines)
2586   puts $aFile "\t\t\t\t<Compiler>"
2587   foreach aFlagIter $aCmplFlagsRelease {
2588     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2589   }
2590   foreach aMacro $theDefines {
2591     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2592   }
2593   puts $aFile "\t\t\t\t</Compiler>"
2594
2595   puts $aFile "\t\t\t\t<Linker>"
2596   if { $toPassArgsByFile == 1 } {
2597     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkFileName\" />"
2598   }
2599   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/lib\" />"
2600   if { "$thePlatform" == "mac" } {
2601     if { [ lsearch $theLibsList X11 ] >= 0} {
2602       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2603     }
2604   }
2605   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch})\" />"
2606   if { "$thePlatform" == "lin" } {
2607     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/lib\" />"
2608   }
2609   puts $aFile "\t\t\t\t</Linker>"
2610
2611   puts $aFile "\t\t\t</Target>"
2612
2613   # Debug target configuration
2614   puts $aFile "\t\t\t<Target title=\"Debug\">"
2615   if { "$theIsExe" == "true" } {
2616     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bind/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2617     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2618   } else {
2619     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2620       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\" />"
2621     } else {
2622       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/libd/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2623     }
2624     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2625   }
2626   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/objd\" />"
2627   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2628   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2629   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2630     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2631   } else {
2632     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2633   }
2634
2635   # compiler options per TARGET (including defines)
2636   puts $aFile "\t\t\t\t<Compiler>"
2637   foreach aFlagIter $aCmplFlagsDebug {
2638     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2639   }
2640   foreach aMacro $theDefines {
2641     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2642   }
2643   puts $aFile "\t\t\t\t</Compiler>"
2644
2645   puts $aFile "\t\t\t\t<Linker>"
2646   if { $toPassArgsByFile == 1 } {
2647     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkDebFileName\" />"
2648   }
2649   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/libd\" />"
2650   if { "$thePlatform" == "mac" } {
2651     if { [ lsearch $theLibsList X11 ] >= 0} {
2652       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2653     }
2654   }
2655   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch}D)\" />"
2656   if { "$thePlatform" == "lin" } {
2657     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/libd\" />"
2658   }
2659   puts $aFile "\t\t\t\t</Linker>"
2660
2661   puts $aFile "\t\t\t</Target>"
2662
2663   puts $aFile "\t\t</Build>"
2664
2665   # COMMON compiler options
2666   puts $aFile "\t\t<Compiler>"
2667   foreach aFlagIter $aCmplFlags {
2668     puts $aFile "\t\t\t<Add option=\"$aFlagIter\" />"
2669   }
2670   puts $aFile "\t\t\t<Add option=\"\$(CSF_OPT_CMPL)\" />"
2671   foreach anIncPath $theIncPaths {
2672     puts $aFile "\t\t\t<Add directory=\"$anIncPath\" />"
2673   }
2674   puts $aFile "\t\t</Compiler>"
2675
2676   # COMMON linker options
2677   puts $aFile "\t\t<Linker>"
2678   if { "$thePlatform" == "wnt" && "$theCmpl" == "gcc" } {
2679     puts $aFile "\t\t\t<Add option=\"-Wl,--export-all-symbols\" />"
2680   }
2681   foreach aFrameworkName $theFrameworks {
2682     if { "$aFrameworkName" != "" } {
2683       puts $aFile "\t\t\t<Add option=\"-framework $aFrameworkName\" />"
2684     }
2685   }
2686   foreach aLibName $theLibsList {
2687     if { "$aLibName" != "" } {
2688       if { "$theCmpl" == "msvc" } {
2689         puts $aFile "\t\t\t<Add library=\"${aLibName}.lib\" />"
2690       } else {
2691         puts $aFile "\t\t\t<Add library=\"${aLibName}\" />"
2692       }
2693     }
2694   }
2695   puts $aFile "\t\t</Linker>"
2696
2697   # list of sources
2698
2699   set aFileLnkObj ""
2700   set aFileLnkObjd ""
2701   set isFirstSrcFile 1
2702   if { $toPassArgsByFile == 1 } {
2703     set aFileLnkObj  [open $aLnkFilePath    "w"]
2704     set aFileLnkObjd [open $aLnkDebFilePath "w"]
2705   }
2706
2707   foreach aSrcFile $theSrcFiles {
2708     if {[string equal -nocase [file extension $aSrcFile] ".mm"]} {
2709       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2710       puts $aFile "\t\t\t<Option compile=\"1\" />"
2711       puts $aFile "\t\t\t<Option link=\"1\" />"
2712       puts $aFile "\t\t</Unit>"
2713     } elseif {[string equal -nocase [file extension $aSrcFile] ".c"]} {
2714       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2715       puts $aFile "\t\t\t<Option compilerVar=\"CC\" />"
2716       puts $aFile "\t\t</Unit>"
2717     } elseif { $toPassArgsByFile == 1 && $isFirstSrcFile == 0 && [string equal -nocase [file extension $aSrcFile] ".cxx" ] } {
2718       # pass at list single source file to Code::Blocks as is
2719       # and pack the list of other files into the dedicated file to workaround process arguments limits on systems like Windows
2720       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2721       puts $aFile "\t\t\t<Option link=\"0\" />"
2722       puts $aFile "\t\t</Unit>"
2723
2724       set aFileObj  [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/obj/src/"]  $aSrcFile]]
2725       set aFileObjd [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/objd/src/"] $aSrcFile]]
2726       puts -nonewline $aFileLnkObj  "$aFileObj "
2727       puts -nonewline $aFileLnkObjd "$aFileObjd "
2728     } else {
2729       puts $aFile "\t\t<Unit filename=\"$aSrcFile\" />"
2730       set isFirstSrcFile 0
2731     }
2732   }
2733
2734   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2735     close $aFileLnkObj
2736     close $aFileLnkObjd
2737   }
2738
2739   puts $aFile "\t</Project>"
2740   puts $aFile "</CodeBlocks_project_file>"
2741   close $aFile
2742
2743   return $aCbpFilePath
2744 }
2745
2746 # Define libraries to link using only EXTERNLIB file
2747 proc LibToLinkX {thePackage theDummyName theSrcDir theSourceDirOther} {
2748   set aToolKits [LibToLink $thePackage $theSrcDir $theSourceDirOther]
2749   return $aToolKits
2750 }
2751
2752 # Function to generate Xcode workspace and project files
2753 proc OS:MKXCD { theOutDir {theModules {}} {theAllSolution ""} {theLibType "dynamic"} {thePlatform ""} } {
2754
2755   puts stderr "Generating project files for Xcode"
2756
2757   # Generate projects for toolkits and separate workspace for each module
2758   foreach aModule $theModules {
2759     OS:xcworkspace $aModule $aModule $theOutDir
2760     OS:xcodeproj   $aModule          $theOutDir ::THE_GUIDS_LIST $theLibType $thePlatform
2761   }
2762
2763   # Generate single workspace "OCCT" containing projects from all modules
2764   if { "$theAllSolution" != "" } {
2765     OS:xcworkspace $theAllSolution $theModules $theOutDir
2766   }
2767 }
2768
2769 # Generates toolkits sections for Xcode workspace file.
2770 proc OS:xcworkspace:toolkits { theModule } {
2771   set aBuff ""
2772
2773   # Adding toolkits for module in workspace.
2774   foreach aToolKit [osutils:tk:sort [${theModule}:toolkits] "src" ""] {
2775     append aBuff "         <FileRef\n"
2776     append aBuff "            location = \"group:${aToolKit}.xcodeproj\">\n"
2777     append aBuff "         </FileRef>\n"
2778   }
2779
2780   # Adding executables for module, assume one project per cxx file...
2781   foreach aUnit [OS:executable ${theModule}] {
2782     set aUnitLoc $aUnit
2783     set src_files [_get_used_files $aUnit "src" false]
2784     set aSrcFiles {}
2785     foreach s $src_files {
2786       regexp {source ([^\s]+)} $s dummy name
2787       lappend aSrcFiles $name
2788     }
2789     foreach aSrcFile $aSrcFiles {
2790       set aFileExtension [file extension $aSrcFile]
2791       if { $aFileExtension == ".cxx" } {
2792         set aPrjName [file rootname $aSrcFile]
2793         append aBuff "         <FileRef\n"
2794         append aBuff "            location = \"group:${aPrjName}.xcodeproj\">\n"
2795         append aBuff "         </FileRef>\n"
2796       }
2797     }
2798   }
2799
2800   # Removing unnecessary newline character from the end.
2801   set aBuff [string replace $aBuff end end]
2802   return $aBuff
2803 }
2804
2805 # Generates workspace files for Xcode.
2806 proc OS:xcworkspace { theWorkspaceName theModules theOutDir } {
2807   # Creating workspace directory for Xcode.
2808   set aWorkspaceDir "${theOutDir}/${theWorkspaceName}.xcworkspace"
2809   wokUtils:FILES:mkdir $aWorkspaceDir
2810   if { ! [file exists $aWorkspaceDir] } {
2811     puts stderr "Error: Could not create workspace directory \"$aWorkspaceDir\""
2812     return
2813   }
2814
2815   # Creating workspace file.
2816   set aWsFilePath "${aWorkspaceDir}/contents.xcworkspacedata"
2817   set aFile [open $aWsFilePath "w"]
2818
2819   # Adding header and section for main Group.
2820   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
2821   puts $aFile "<Workspace"
2822   puts $aFile "   version = \"1.0\">"
2823   puts $aFile "   <Group"
2824   puts $aFile "      location = \"container:\""
2825   puts $aFile "      name = \"${theWorkspaceName}\">"
2826
2827   # Adding modules.
2828   if { [llength "$theModules"] > 1 } {
2829     foreach aModule $theModules {
2830       puts $aFile "      <Group"
2831       puts $aFile "         location = \"container:\""
2832       puts $aFile "         name = \"${aModule}\">"
2833       puts $aFile [OS:xcworkspace:toolkits $aModule]
2834       puts $aFile "      </Group>"
2835     }
2836   } else {
2837     puts $aFile [OS:xcworkspace:toolkits $theModules]
2838   }
2839
2840   # Adding footer.
2841   puts $aFile "   </Group>"
2842   puts $aFile "</Workspace>"
2843   close $aFile
2844 }
2845
2846 # Generates Xcode project files.
2847 proc OS:xcodeproj { theModules theOutDir theGuidsMap theLibType thePlatform} {
2848   upvar $theGuidsMap aGuidsMap
2849
2850   set isStatic 0
2851   if { "$theLibType" == "static" } {
2852     set isStatic 1
2853   } elseif { "$thePlatform" == "ios" } {
2854     set isStatic 1
2855   }
2856
2857   set aProjectFiles {}
2858   foreach aModule $theModules {
2859     foreach aToolKit [${aModule}:toolkits] {
2860       lappend aProjectFiles [osutils:xcdtk $theOutDir $aToolKit     aGuidsMap $isStatic $thePlatform "dylib"]
2861     }
2862     foreach anExecutable [OS:executable ${aModule}] {
2863       lappend aProjectFiles [osutils:xcdtk $theOutDir $anExecutable aGuidsMap $isStatic $thePlatform "executable"]
2864     }
2865   }
2866   return $aProjectFiles
2867 }
2868
2869 # Generates dependencies section for Xcode project files.
2870 proc osutils:xcdtk:deps {theToolKit theTargetType theGuidsMap theFileRefSection theDepsGuids theDepsRefGuids thePlatform theIsStatic} {
2871   upvar $theGuidsMap         aGuidsMap
2872   upvar $theFileRefSection   aFileRefSection
2873   upvar $theDepsGuids        aDepsGuids
2874   upvar $theDepsRefGuids     aDepsRefGuids
2875
2876   set aBuildFileSection ""
2877   set aUsedLibs         [wokUtils:LIST:Purge [osutils:tk:close $theToolKit "src" ""]]
2878   set aDepToolkits      [lappend [wokUtils:LIST:Purge [osutils:tk:close $theToolKit "src" ""]] $theToolKit]
2879
2880   if { "$theTargetType" == "executable" } {
2881     set aFile [osutils:tk:cxxfiles $theToolKit mac "src"]
2882     set aProjName [file rootname [file tail $aFile]]
2883     set aDepToolkits [LibToLinkX $theToolKit $aProjName "src" ""]
2884   }
2885
2886   set aLibExt "dylib"
2887   if { $theIsStatic == 1 } {
2888     set aLibExt "a"
2889     if { "$theTargetType" != "executable" } {
2890       return $aBuildFileSection
2891     }
2892   }
2893
2894   osutils:usedOsLibs $theToolKit $thePlatform aLibs aFrameworks "src"
2895   set aUsedLibs [concat $aUsedLibs $aLibs]
2896   set aUsedLibs [concat $aUsedLibs $aFrameworks]
2897   foreach tkx $aUsedLibs {
2898     set aDepLib    "${tkx}_Dep"
2899     set aDepLibRef "${tkx}_DepRef"
2900
2901     if { ! [info exists aGuidsMap($aDepLib)] } {
2902       set aGuidsMap($aDepLib) [OS:genGUID "xcd"]
2903     }
2904     if { ! [info exists aGuidsMap($aDepLibRef)] } {
2905       set aGuidsMap($aDepLibRef) [OS:genGUID "xcd"]
2906     }
2907
2908     append aBuildFileSection "\t\t$aGuidsMap($aDepLib) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aDepLibRef) ; \};\n"
2909     if {[lsearch -nocase $aFrameworks $tkx] == -1} {
2910       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = file; name = lib${tkx}.${aLibExt}; path = lib${tkx}.${aLibExt}; sourceTree = \"<group>\"; \};\n"
2911     } else {
2912       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ${tkx}.framework; path = /System/Library/Frameworks/${tkx}.framework; sourceTree = \"<absolute>\"; \};\n"
2913     }
2914     append aDepsGuids        "\t\t\t\t$aGuidsMap($aDepLib) ,\n"
2915     append aDepsRefGuids     "\t\t\t\t$aGuidsMap($aDepLibRef) ,\n"
2916   }
2917
2918   return $aBuildFileSection
2919 }
2920
2921 # Generates PBXBuildFile and PBXGroup sections for project file.
2922 proc osutils:xcdtk:sources {theToolKit theTargetType theSrcFileRefSection theGroupSection thePackageGuids theSrcFileGuids theGuidsMap theIncPaths} {
2923   upvar $theSrcFileRefSection aSrcFileRefSection
2924   upvar $theGroupSection      aGroupSection
2925   upvar $thePackageGuids      aPackagesGuids
2926   upvar $theSrcFileGuids      aSrcFileGuids
2927   upvar $theGuidsMap          aGuidsMap
2928   upvar $theIncPaths          anIncPaths
2929
2930   set listloc [osutils:tk:units $theToolKit "src"]
2931   set aBuildFileSection ""
2932   set aPackages [lsort -nocase $listloc]
2933   if { "$theTargetType" == "executable" } {
2934     set aPackages [list "$theToolKit"]
2935   }
2936
2937   # Generating PBXBuildFile, PBXGroup sections and groups for each package.
2938   foreach fxlo $aPackages {
2939     set xlo       $fxlo
2940     set aPackage "${xlo}_Package"
2941     set aSrcFileRefGuids ""
2942     if { ! [info exists aGuidsMap($aPackage)] } {
2943       set aGuidsMap($aPackage) [OS:genGUID "xcd"]
2944     }
2945
2946     set aSrcFiles [osutils:tk:cxxfiles $xlo mac "src"]
2947     foreach aSrcFile [lsort $aSrcFiles] {
2948       set aFileExt "sourcecode.cpp.cpp"
2949
2950       if { [file extension $aSrcFile] == ".c" } {
2951         set aFileExt "sourcecode.c.c"
2952       } elseif { [file extension $aSrcFile] == ".mm" } {
2953         set aFileExt "sourcecode.cpp.objcpp"
2954       }
2955
2956       if { ! [info exists aGuidsMap($aSrcFile)] } {
2957         set aGuidsMap($aSrcFile) [OS:genGUID "xcd"]
2958       }
2959       set aSrcFileRef "${aSrcFile}_Ref"
2960       if { ! [info exists aGuidsMap($aSrcFileRef)] } {
2961         set aGuidsMap($aSrcFileRef) [OS:genGUID "xcd"]
2962       }
2963       if { ! [info exists written([file tail $aSrcFile])] } {
2964         set written([file tail $aSrcFile]) 1
2965         append aBuildFileSection  "\t\t$aGuidsMap($aSrcFile) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aSrcFileRef) ;\};\n"
2966         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"
2967         append aSrcFileGuids      "\t\t\t\t$aGuidsMap($aSrcFile) ,\n"
2968         append aSrcFileRefGuids   "\t\t\t\t$aGuidsMap($aSrcFileRef) ,\n"
2969       } else {
2970         puts "Warning : more than one occurrences for [file tail $aSrcFile]"
2971       }
2972     }
2973
2974     append aGroupSection "\t\t$aGuidsMap($aPackage) = \{\n"
2975     append aGroupSection "\t\t\tisa = PBXGroup;\n"
2976     append aGroupSection "\t\t\tchildren = (\n"
2977     append aGroupSection $aSrcFileRefGuids
2978     append aGroupSection "\t\t\t);\n"
2979     append aGroupSection "\t\t\tname = $xlo;\n"
2980     append aGroupSection "\t\t\tsourceTree = \"<group>\";\n"
2981     append aGroupSection "\t\t\};\n"
2982
2983     # Storing packages IDs for adding them later as a child of toolkit
2984     append aPackagesGuids "\t\t\t\t$aGuidsMap($aPackage) ,\n"
2985   }
2986
2987   # Removing unnecessary newline character from the end.
2988   set aPackagesGuids [string replace $aPackagesGuids end end]
2989
2990   return $aBuildFileSection
2991 }
2992
2993 # Creates folders structure and all necessary files for Xcode project.
2994 proc osutils:xcdtk { theOutDir theToolKit theGuidsMap theIsStatic thePlatform {theTargetType "dylib"} } {
2995   set aPBXBuildPhase "Headers"
2996   set aRunOnlyForDeployment "0"
2997   set aProductType "library.dynamic"
2998   set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = dylib;"
2999   set anExecPrefix "\t\t\t\tEXECUTABLE_PREFIX = lib;"
3000   set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = dylib;"
3001   set aTKDefines [list "OCC_CONVERT_SIGNALS"]
3002   if { $theIsStatic == 1 } {
3003     lappend aTKDefines "OCCT_NO_PLUGINS"
3004   }
3005
3006   if { "$theTargetType" == "executable" } {
3007     set aPBXBuildPhase "CopyFiles"
3008     set aRunOnlyForDeployment "1"
3009     set aProductType "tool"
3010     set anExecExtension ""
3011     set anExecPrefix ""
3012     set aWrapperExtension ""
3013   } elseif { $theIsStatic == 1 } {
3014     set aProductType "library.static"
3015     set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = a;"
3016     set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = a;"
3017   }
3018
3019   set aUsername [exec whoami]
3020
3021   # Creation of folders for Xcode projectP.
3022   set aToolkitDir "${theOutDir}/${theToolKit}.xcodeproj"
3023   wokUtils:FILES:mkdir $aToolkitDir
3024   if { ! [file exists $aToolkitDir] } {
3025     puts stderr "Error: Could not create project directory \"$aToolkitDir\""
3026     return
3027   }
3028
3029   set aUserDataDir "${aToolkitDir}/xcuserdata"
3030   wokUtils:FILES:mkdir $aUserDataDir
3031   if { ! [file exists $aUserDataDir] } {
3032     puts stderr "Error: Could not create xcuserdata directory in \"$aToolkitDir\""
3033     return
3034   }
3035
3036   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
3037   wokUtils:FILES:mkdir $aUserDataDir
3038   if { ! [file exists $aUserDataDir] } {
3039     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directory in \"$aToolkitDir\"/xcuserdata"
3040     return
3041   }
3042
3043   set aSchemesDir "${aUserDataDir}/xcschemes"
3044   wokUtils:FILES:mkdir $aSchemesDir
3045   if { ! [file exists $aSchemesDir] } {
3046     puts stderr "Error: Could not create xcschemes directory in \"$aUserDataDir\""
3047     return
3048   }
3049   # End of folders creation.
3050
3051   # Generating GUID for toolkit.
3052   upvar $theGuidsMap aGuidsMap
3053   if { ! [info exists aGuidsMap($theToolKit)] } {
3054     set aGuidsMap($theToolKit) [OS:genGUID "xcd"]
3055   }
3056
3057   # Creating xcscheme file for toolkit from template.
3058   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcd"]
3059   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theToolKit aXcschemeTmpl
3060   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theToolKit) aXcschemeTmpl
3061   set aXcschemeFile [open "$aSchemesDir/${theToolKit}.xcscheme"  "w"]
3062   puts $aXcschemeFile $aXcschemeTmpl
3063   close $aXcschemeFile
3064
3065   # Creating xcschememanagement.plist file for toolkit from template.
3066   set aPlistTmpl [osutils:readtemplate "plist" "xcd"]
3067   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theToolKit aPlistTmpl
3068   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theToolKit) aPlistTmpl
3069   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
3070   puts $aPlistFile $aPlistTmpl
3071   close $aPlistFile
3072
3073   # Creating project.pbxproj file for toolkit.
3074   set aPbxprojFile [open "$aToolkitDir/project.pbxproj" "w"]
3075   puts $aPbxprojFile "// !\$*UTF8*\$!"
3076   puts $aPbxprojFile "\{"
3077   puts $aPbxprojFile "\tarchiveVersion = 1;"
3078   puts $aPbxprojFile "\tclasses = \{"
3079   puts $aPbxprojFile "\t\};"
3080   puts $aPbxprojFile "\tobjectVersion = 46;"
3081   puts $aPbxprojFile "\tobjects = \{\n"
3082
3083   # Begin PBXBuildFile section
3084   set aPackagesGuids ""
3085   set aGroupSection ""
3086   set aSrcFileRefSection ""
3087   set aSrcFileGuids ""
3088   set aDepsFileRefSection ""
3089   set aDepsGuids ""
3090   set aDepsRefGuids ""
3091   set anIncPaths [list "../../../inc"]
3092   set anLibPaths ""
3093
3094   if { [info exists ::env(CSF_OPT_INC)] } {
3095     set anIncCfg [split "$::env(CSF_OPT_INC)" ":"]
3096     foreach anIncCfgPath $anIncCfg {
3097       lappend anIncPaths $anIncCfgPath
3098     }
3099   }
3100   if { [info exists ::env(CSF_OPT_LIB64)] } {
3101     set anLibCfg [split "$::env(CSF_OPT_LIB64)" ":"]
3102     foreach anLibCfgPath $anLibCfg {
3103       lappend anLibPaths $anLibCfgPath
3104     }
3105   }
3106
3107   puts $aPbxprojFile [osutils:xcdtk:sources $theToolKit $theTargetType aSrcFileRefSection aGroupSection aPackagesGuids aSrcFileGuids aGuidsMap anIncPaths]
3108   puts $aPbxprojFile [osutils:xcdtk:deps    $theToolKit $theTargetType aGuidsMap aDepsFileRefSection aDepsGuids aDepsRefGuids $thePlatform $theIsStatic]
3109   # End PBXBuildFile section
3110
3111   # Begin PBXFileReference section
3112   set aToolkitLib "lib${theToolKit}.dylib"
3113   set aPath "$aToolkitLib"
3114   if { "$theTargetType" == "executable" } {
3115     set aPath "$theToolKit"
3116   } elseif { $theIsStatic == 1 } {
3117     set aToolkitLib "lib${theToolKit}.a"
3118   }
3119
3120   if { ! [info exists aGuidsMap($aToolkitLib)] } {
3121     set aGuidsMap($aToolkitLib) [OS:genGUID "xcd"]
3122   }
3123
3124   puts $aPbxprojFile "\t\t$aGuidsMap($aToolkitLib) = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.${theTargetType}\"; includeInIndex = 0; path = $aPath; sourceTree = BUILT_PRODUCTS_DIR; };\n"
3125   puts $aPbxprojFile $aSrcFileRefSection
3126   puts $aPbxprojFile $aDepsFileRefSection
3127   # End PBXFileReference section
3128
3129
3130   # Begin PBXFrameworksBuildPhase section
3131   set aTkFrameworks "${theToolKit}_Frameworks"
3132   if { ! [info exists aGuidsMap($aTkFrameworks)] } {
3133     set aGuidsMap($aTkFrameworks) [OS:genGUID "xcd"]
3134   }
3135
3136   puts $aPbxprojFile "\t\t$aGuidsMap($aTkFrameworks) = \{"
3137   puts $aPbxprojFile "\t\t\tisa = PBXFrameworksBuildPhase;"
3138   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3139   puts $aPbxprojFile "\t\t\tfiles = ("
3140   puts $aPbxprojFile $aDepsGuids
3141   puts $aPbxprojFile "\t\t\t);"
3142   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
3143   puts $aPbxprojFile "\t\t\};\n"
3144   # End PBXFrameworksBuildPhase section
3145
3146   # Begin PBXGroup section
3147   set aTkPBXGroup "${theToolKit}_PBXGroup"
3148   if { ! [info exists aGuidsMap($aTkPBXGroup)] } {
3149     set aGuidsMap($aTkPBXGroup) [OS:genGUID "xcd"]
3150   }
3151
3152   set aTkSrcGroup "${theToolKit}_SrcGroup"
3153   if { ! [info exists aGuidsMap($aTkSrcGroup)] } {
3154     set aGuidsMap($aTkSrcGroup) [OS:genGUID "xcd"]
3155   }
3156
3157   puts $aPbxprojFile $aGroupSection
3158   puts $aPbxprojFile "\t\t$aGuidsMap($aTkPBXGroup) = \{"
3159   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
3160   puts $aPbxprojFile "\t\t\tchildren = ("
3161   puts $aPbxprojFile $aDepsRefGuids
3162   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSrcGroup) ,"
3163   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aToolkitLib) ,"
3164   puts $aPbxprojFile "\t\t\t);"
3165   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
3166   puts $aPbxprojFile "\t\t\};"
3167   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSrcGroup) = \{"
3168   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
3169   puts $aPbxprojFile "\t\t\tchildren = ("
3170   puts $aPbxprojFile $aPackagesGuids
3171   puts $aPbxprojFile "\t\t\t);"
3172   puts $aPbxprojFile "\t\t\tname = \"Source files\";"
3173   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
3174   puts $aPbxprojFile "\t\t\};\n"
3175   # End PBXGroup section
3176
3177   # Begin PBXHeadersBuildPhase section
3178   set aTkHeaders "${theToolKit}_Headers"
3179   if { ! [info exists aGuidsMap($aTkHeaders)] } {
3180     set aGuidsMap($aTkHeaders) [OS:genGUID "xcd"]
3181   }
3182
3183   puts $aPbxprojFile "\t\t$aGuidsMap($aTkHeaders) = \{"
3184   puts $aPbxprojFile "\t\t\tisa = PBX${aPBXBuildPhase}BuildPhase;"
3185   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3186   puts $aPbxprojFile "\t\t\tfiles = ("
3187   puts $aPbxprojFile "\t\t\t);"
3188   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = ${aRunOnlyForDeployment};"
3189   puts $aPbxprojFile "\t\t\};\n"
3190   # End PBXHeadersBuildPhase section
3191
3192   # Begin PBXNativeTarget section
3193   set aTkBuildCfgListNativeTarget "${theToolKit}_BuildCfgListNativeTarget"
3194   if { ! [info exists aGuidsMap($aTkBuildCfgListNativeTarget)] } {
3195     set aGuidsMap($aTkBuildCfgListNativeTarget) [OS:genGUID "xcd"]
3196   }
3197
3198   set aTkSources "${theToolKit}_Sources"
3199   if { ! [info exists aGuidsMap($aTkSources)] } {
3200     set aGuidsMap($aTkSources) [OS:genGUID "xcd"]
3201   }
3202
3203   puts $aPbxprojFile "\t\t$aGuidsMap($theToolKit) = \{"
3204   puts $aPbxprojFile "\t\t\tisa = PBXNativeTarget;"
3205   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListNativeTarget) ;"
3206   puts $aPbxprojFile "\t\t\tbuildPhases = ("
3207   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSources) ,"
3208   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkFrameworks) ,"
3209   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkHeaders) ,"
3210   puts $aPbxprojFile "\t\t\t);"
3211   puts $aPbxprojFile "\t\t\tbuildRules = ("
3212   puts $aPbxprojFile "\t\t\t);"
3213   puts $aPbxprojFile "\t\t\tdependencies = ("
3214   puts $aPbxprojFile "\t\t\t);"
3215   puts $aPbxprojFile "\t\t\tname = $theToolKit;"
3216   puts $aPbxprojFile "\t\t\tproductName = $theToolKit;"
3217   puts $aPbxprojFile "\t\t\tproductReference = $aGuidsMap($aToolkitLib) ;"
3218   puts $aPbxprojFile "\t\t\tproductType = \"com.apple.product-type.${aProductType}\";"
3219   puts $aPbxprojFile "\t\t\};\n"
3220   # End PBXNativeTarget section
3221
3222   # Begin PBXProject section
3223   set aTkProjectObj "${theToolKit}_ProjectObj"
3224   if { ! [info exists aGuidsMap($aTkProjectObj)] } {
3225     set aGuidsMap($aTkProjectObj) [OS:genGUID "xcd"]
3226   }
3227
3228   set aTkBuildCfgListProj "${theToolKit}_BuildCfgListProj"
3229   if { ! [info exists aGuidsMap($aTkBuildCfgListProj)] } {
3230     set aGuidsMap($aTkBuildCfgListProj) [OS:genGUID "xcd"]
3231   }
3232
3233   puts $aPbxprojFile "\t\t$aGuidsMap($aTkProjectObj) = \{"
3234   puts $aPbxprojFile "\t\t\tisa = PBXProject;"
3235   puts $aPbxprojFile "\t\t\tattributes = \{"
3236   puts $aPbxprojFile "\t\t\t\tLastUpgradeCheck = 0430;"
3237   puts $aPbxprojFile "\t\t\t\};"
3238   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListProj) ;"
3239   puts $aPbxprojFile "\t\t\tcompatibilityVersion = \"Xcode 3.2\";"
3240   puts $aPbxprojFile "\t\t\tdevelopmentRegion = English;"
3241   puts $aPbxprojFile "\t\t\thasScannedForEncodings = 0;"
3242   puts $aPbxprojFile "\t\t\tknownRegions = ("
3243   puts $aPbxprojFile "\t\t\t\ten,"
3244   puts $aPbxprojFile "\t\t\t);"
3245   puts $aPbxprojFile "\t\t\tmainGroup = $aGuidsMap($aTkPBXGroup);"
3246   puts $aPbxprojFile "\t\t\tproductRefGroup = $aGuidsMap($aTkPBXGroup);"
3247   puts $aPbxprojFile "\t\t\tprojectDirPath = \"\";"
3248   puts $aPbxprojFile "\t\t\tprojectRoot = \"\";"
3249   puts $aPbxprojFile "\t\t\ttargets = ("
3250   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($theToolKit) ,"
3251   puts $aPbxprojFile "\t\t\t);"
3252   puts $aPbxprojFile "\t\t\};\n"
3253   # End PBXProject section
3254
3255   # Begin PBXSourcesBuildPhase section
3256   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSources) = \{"
3257   puts $aPbxprojFile "\t\t\tisa = PBXSourcesBuildPhase;"
3258   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3259   puts $aPbxprojFile "\t\t\tfiles = ("
3260   puts $aPbxprojFile $aSrcFileGuids
3261   puts $aPbxprojFile "\t\t\t);"
3262   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
3263   puts $aPbxprojFile "\t\t\};\n"
3264   # End PBXSourcesBuildPhase section
3265
3266   # Begin XCBuildConfiguration section
3267   set aTkDebugProject "${theToolKit}_DebugProject"
3268   if { ! [info exists aGuidsMap($aTkDebugProject)] } {
3269     set aGuidsMap($aTkDebugProject) [OS:genGUID "xcd"]
3270   }
3271
3272   set aTkReleaseProject "${theToolKit}_ReleaseProject"
3273   if { ! [info exists aGuidsMap($aTkReleaseProject)] } {
3274     set aGuidsMap($aTkReleaseProject) [OS:genGUID "xcd"]
3275   }
3276
3277   set aTkDebugNativeTarget "${theToolKit}_DebugNativeTarget"
3278   if { ! [info exists aGuidsMap($aTkDebugNativeTarget)] } {
3279     set aGuidsMap($aTkDebugNativeTarget) [OS:genGUID "xcd"]
3280   }
3281
3282   set aTkReleaseNativeTarget "${theToolKit}_ReleaseNativeTarget"
3283   if { ! [info exists aGuidsMap($aTkReleaseNativeTarget)] } {
3284     set aGuidsMap($aTkReleaseNativeTarget) [OS:genGUID "xcd"]
3285   }
3286
3287   # Debug target
3288   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugProject) = \{"
3289   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3290   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3291
3292   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;"
3293   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3294   if { "$thePlatform" == "ios" } {
3295     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3296     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3297     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3298     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3299   }
3300   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3301   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3302   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3303   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = NO;"
3304   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3305   puts $aPbxprojFile "\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;"
3306   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3307   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;"
3308   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3309   puts $aPbxprojFile "\t\t\t\t\t\"DEBUG=1\","
3310   puts $aPbxprojFile "\t\t\t\t\t\"\$\(inherited\)\","
3311   puts $aPbxprojFile "\t\t\t\t);"
3312   puts $aPbxprojFile "\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;"
3313   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3314   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3315   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3316   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3317   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3318   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64D)\"; "
3319   if { "$thePlatform" == "ios" } {
3320     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = NO;"
3321     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3322   } else {
3323     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = YES;"
3324   }
3325   puts $aPbxprojFile "\t\t\t\};"
3326
3327   puts $aPbxprojFile "\t\t\tname = Debug;"
3328   puts $aPbxprojFile "\t\t\};"
3329
3330   # Release target
3331   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseProject) = \{"
3332   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3333   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3334
3335   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";"
3336   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3337   if { "$thePlatform" == "ios" } {
3338     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3339     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3340     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3341     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3342   }
3343   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3344   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3345   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3346   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = YES;"
3347   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3348   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3349   puts $aPbxprojFile "\t\t\t\tDEAD_CODE_STRIPPING = NO;"
3350   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 2;"
3351   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3352   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3353   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3354   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3355   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3356   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64)\";"
3357   if { "$thePlatform" == "ios" } {
3358     puts $aPbxprojFile "\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;"
3359     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3360   }
3361   puts $aPbxprojFile "\t\t\t\};"
3362   puts $aPbxprojFile "\t\t\tname = Release;"
3363   puts $aPbxprojFile "\t\t\};"
3364   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugNativeTarget) = \{"
3365   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3366   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3367   puts $aPbxprojFile "${anExecExtension}"
3368   puts $aPbxprojFile "${anExecPrefix}"
3369   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3370   foreach aMacro $aTKDefines {
3371     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3372   }
3373   puts $aPbxprojFile "\t\t\t\t);"
3374
3375   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3376   foreach anIncPath $anIncPaths {
3377     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3378   }
3379   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3380   puts $aPbxprojFile "\t\t\t\t);"
3381
3382   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3383   foreach anLibPath $anLibPaths {
3384     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3385   }
3386   puts $aPbxprojFile "\t\t\t\t);"
3387
3388   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3389   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3390   puts $aPbxprojFile "\t\t\t\t);"
3391   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3392   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3393   puts $aPbxprojFile "\t\t\t\t);"
3394   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3395   set anUserHeaderSearchPath "\t\t\t\tUSER_HEADER_SEARCH_PATHS = \""
3396   foreach anIncPath $anIncPaths {
3397     append anUserHeaderSearchPath " ${anIncPath}"
3398   }
3399   append anUserHeaderSearchPath "\";"
3400   puts $aPbxprojFile $anUserHeaderSearchPath
3401   puts $aPbxprojFile "${aWrapperExtension}"
3402   puts $aPbxprojFile "\t\t\t\};"
3403   puts $aPbxprojFile "\t\t\tname = Debug;"
3404   puts $aPbxprojFile "\t\t\};"
3405   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseNativeTarget) = \{"
3406   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3407   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3408   puts $aPbxprojFile "${anExecExtension}"
3409   puts $aPbxprojFile "${anExecPrefix}"
3410   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3411   foreach aMacro $aTKDefines {
3412     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3413   }
3414   puts $aPbxprojFile "\t\t\t\t);"
3415   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3416   foreach anIncPath $anIncPaths {
3417     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3418   }
3419   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3420   puts $aPbxprojFile "\t\t\t\t);"
3421
3422   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3423   foreach anLibPath $anLibPaths {
3424     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3425   }
3426   puts $aPbxprojFile "\t\t\t\t);"
3427
3428   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3429   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3430   puts $aPbxprojFile "\t\t\t\t);"
3431   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3432   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3433   puts $aPbxprojFile "\t\t\t\t);"
3434   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3435   puts $aPbxprojFile $anUserHeaderSearchPath
3436   puts $aPbxprojFile "${aWrapperExtension}"
3437   puts $aPbxprojFile "\t\t\t\};"
3438   puts $aPbxprojFile "\t\t\tname = Release;"
3439   puts $aPbxprojFile "\t\t\};\n"
3440   # End XCBuildConfiguration section
3441
3442   # Begin XCConfigurationList section
3443   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListProj) = \{"
3444   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3445   puts $aPbxprojFile "\t\tbuildConfigurations = ("
3446   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugProject) ,"
3447   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseProject) ,"
3448   puts $aPbxprojFile "\t\t\t);"
3449   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3450   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3451   puts $aPbxprojFile "\t\t\};"
3452   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListNativeTarget) = \{"
3453   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3454   puts $aPbxprojFile "\t\t\tbuildConfigurations = ("
3455   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugNativeTarget) ,"
3456   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseNativeTarget) ,"
3457   puts $aPbxprojFile "\t\t\t);"
3458   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3459   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3460   puts $aPbxprojFile "\t\t\};\n"
3461   # End XCConfigurationList section
3462
3463   puts $aPbxprojFile "\t\};"
3464   puts $aPbxprojFile "\trootObject = $aGuidsMap($aTkProjectObj) ;"
3465   puts $aPbxprojFile "\}"
3466
3467   close $aPbxprojFile
3468 }
3469
3470 proc osutils:xcdx { theOutDir theExecutable theGuidsMap } {
3471   set aUsername [exec whoami]
3472
3473   # Creating folders for Xcode project file.
3474   set anExecutableDir "${theOutDir}/${theExecutable}.xcodeproj"
3475   wokUtils:FILES:mkdir $anExecutableDir
3476   if { ! [file exists $anExecutableDir] } {
3477     puts stderr "Error: Could not create project directory \"$anExecutableDir\""
3478     return
3479   }
3480
3481   set aUserDataDir "${anExecutableDir}/xcuserdata"
3482   wokUtils:FILES:mkdir $aUserDataDir
3483   if { ! [file exists $aUserDataDir] } {
3484     puts stderr "Error: Could not create xcuserdata directory in \"$anExecutableDir\""
3485     return
3486   }
3487
3488   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
3489   wokUtils:FILES:mkdir $aUserDataDir
3490   if { ! [file exists $aUserDataDir] } {
3491     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directory in \"$anExecutableDir\"/xcuserdata"
3492     return
3493   }
3494
3495   set aSchemesDir "${aUserDataDir}/xcschemes"
3496   wokUtils:FILES:mkdir $aSchemesDir
3497   if { ! [file exists $aSchemesDir] } {
3498     puts stderr "Error: Could not create xcschemes directory in \"$aUserDataDir\""
3499     return
3500   }
3501   # End folders creation.
3502
3503   # Generating GUID for toolkit.
3504   upvar $theGuidsMap aGuidsMap
3505   if { ! [info exists aGuidsMap($theExecutable)] } {
3506     set aGuidsMap($theExecutable) [OS:genGUID "xcd"]
3507   }
3508
3509   # Creating xcscheme file for toolkit from template.
3510   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcode"]
3511   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theExecutable aXcschemeTmpl
3512   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theExecutable) aXcschemeTmpl
3513   set aXcschemeFile [open "$aSchemesDir/${theExecutable}.xcscheme"  "w"]
3514   puts $aXcschemeFile $aXcschemeTmpl
3515   close $aXcschemeFile
3516
3517   # Creating xcschememanagement.plist file for toolkit from template.
3518   set aPlistTmpl [osutils:readtemplate "plist" "xcode"]
3519   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theExecutable aPlistTmpl
3520   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theExecutable) aPlistTmpl
3521   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
3522   puts $aPlistFile $aPlistTmpl
3523   close $aPlistFile
3524 }
3525
3526 # Returns available Windows SDKs versions
3527 proc osutils:sdk { theSdkMajorVer {isQuietMode false} {theSdkDirectories {}} } {
3528   if { ![llength ${theSdkDirectories}] } {
3529     foreach anEnvVar { "ProgramFiles" "ProgramFiles\(x86\)" "ProgramW6432" } {
3530       if {[ info exists ::env(${anEnvVar}) ]} {
3531         lappend theSdkDirectories "$::env(${anEnvVar})/Windows Kits/${theSdkMajorVer}/Include"
3532       }
3533     }
3534   }
3535
3536   set sdk_versions {}
3537   foreach sdk_dir ${theSdkDirectories} {
3538     if { [file isdirectory ${sdk_dir}] } {
3539       lappend sdk_versions [glob -tails -directory "${sdk_dir}" -type d *]
3540     }
3541   }
3542
3543   if {![llength ${sdk_versions}] && !${isQuietMode}} {
3544     error "Error : Could not find Windows SDK ${theSdkMajorVer}"
3545   }
3546
3547   return [join [lsort -unique ${sdk_versions}] " "]
3548 }
3549
3550 # Generate global properties to Visual Studio project file for UWP solution
3551 proc osutils:uwp:proj { isUWP theProjTmpl } {
3552
3553   set uwp_properties ""
3554   set uwp_generate_metadata ""
3555   set uwp_app_container ""
3556
3557   set format_template ""
3558
3559   if { $isUWP } {
3560     set sdk_versions [osutils:sdk 10]
3561     set sdk_max_ver [lindex ${sdk_versions} end]
3562
3563     set uwp_properties "<DefaultLanguage>en-US</DefaultLanguage>\n   \
3564 <ApplicationType>Windows Store</ApplicationType>\n   \
3565 <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\n   \
3566 <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\n   \
3567 <AppContainerApplication>true</AppContainerApplication>\n   \
3568 <WindowsTargetPlatformVersion>${sdk_max_ver}</WindowsTargetPlatformVersion>\n   \
3569 <WindowsTargetPlatformMinVersion>${sdk_max_ver}</WindowsTargetPlatformMinVersion>"
3570
3571     set uwp_generate_metadata        "<GenerateWindowsMetadata>false</GenerateWindowsMetadata>"
3572
3573     regsub -all -- {[\r\n\s]*<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>} ${theProjTmpl} "" theProjTmpl
3574   } else {
3575     set format_template "\[\\r\\n\\s\]*"
3576   }
3577
3578   regsub -all -- "${format_template}__UWP_PROPERTIES__"        ${theProjTmpl} "${uwp_properties}" theProjTmpl
3579   regsub -all -- "${format_template}__UWP_GENERATE_METADATA__" ${theProjTmpl} "${uwp_generate_metadata}" theProjTmpl
3580
3581   return ${theProjTmpl}
3582 }
3583
3584 # Report all files found in package directory but not listed in FILES
3585 proc osutils:checksrcfiles { theUnit theSrcDir} {
3586   global path
3587   set aCasRoot [file normalize ${path}]
3588
3589   if {![file isdirectory ${aCasRoot}]} {
3590     puts "OCCT directory is not defined correctly: ${aCasRoot}"
3591     return
3592   }
3593
3594   set anUnitAbsPath [file normalize "${aCasRoot}/$theSrcDir/${theUnit}"]
3595
3596   if {[file exists "${anUnitAbsPath}/FILES"]} {
3597     set aFilesFile [open "${anUnitAbsPath}/FILES" rb]
3598     set aFilesFileList [split [read ${aFilesFile}] "\n"]
3599     close ${aFilesFile}
3600
3601     set aFilesFileList [lsearch -inline -all -not -exact ${aFilesFileList} ""]
3602
3603     # report all files not listed in FILES
3604     set anAllFiles [glob -tails -nocomplain -dir ${anUnitAbsPath} "*"]
3605     foreach aFile ${anAllFiles} {
3606       if { "${aFile}" == "FILES" } {
3607         continue
3608       }
3609       if { "${aFile}" == "icons" } {
3610         continue
3611       }
3612       if { [lsearch -exact ${aFilesFileList} ${aFile}] == -1 } {
3613         puts "Warning: file ${anUnitAbsPath}/${aFile} is not listed in ${anUnitAbsPath}/FILES!"
3614       }
3615     }
3616   }
3617 }