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