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