0030749: Inspectors - compilation under tcl scripts
[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 Modules]
494   if { "$thePlatform" == "ios" } {
495     set goaway [list Draw]
496     set aModules [osutils:juststation $goaway $aModules]
497   }
498
499   # Draw module is turned off due to it is not supported on UWP
500   if { $isUWP } {
501     set aDrawIndex [lsearch -exact ${aModules} "Draw"]
502     if { ${aDrawIndex} != -1 } {
503       set aModules [lreplace ${aModules} ${aDrawIndex} ${aDrawIndex}]
504     }
505   }
506
507   # create the out dir if it does not exist
508   if (![file isdirectory $path/inc]) {
509     puts "$path/inc folder does not exists and will be created"
510     wokUtils:FILES:mkdir $path/inc
511   }
512
513   # collect all required header files
514   puts "Collecting required header files into $path/inc ..."
515   osutils:collectinc $aModules "src" $path/inc
516
517   # make list of Inspector tools
518   set aTools {}
519   if { "$::BUILD_Inspector" == "true" } {
520     set aTools [OS:init Tools]
521
522     # create the out dir if it does not exist
523     if (![file isdirectory $path/inc/inspector]) {
524      puts "$path/inc/inspector folder does not exists and will be created"
525      wokUtils:FILES:mkdir $path/inc/inspector
526     }
527
528     # collect all required header files
529     puts "Collecting required tools header files into $path/inc/inspector ..."
530     osutils:collectinc $aTools "tools" $path/inc/inspector
531   }
532
533   if { "$theFormat" == "pro" } {
534     return
535   }
536
537   wokUtils:FILES:mkdir $anOutDir
538   if { ![file exists $anOutDir] } {
539     puts stderr "Error: Could not create output directory \"$anOutDir\""
540     return
541   }
542
543   # Generating project files for the selected format
544   switch -exact -- "$theFormat" {
545     "vc7"   -
546     "vc8"   -
547     "vc9"   -
548     "vc10"  -
549     "vc11"  -
550     "vc12"  -
551     "vc14"  -
552     "vc141" -
553     "vc142" -
554     "vclang"   { OS:MKVC  $anOutDir $aModules $aTools $theSolution $theFormat $isUWP}
555     "cbp"      { OS:MKCBP $anOutDir $aModules $theSolution $thePlatform $theCmpl }
556     "xcd"      {
557       set ::THE_GUIDS_LIST($::aTKNullKey) "000000000000000000000000"
558       OS:MKXCD $anOutDir $aModules $theSolution $theLibType $thePlatform
559     }
560   }
561
562   # Store generated GUIDs map
563   set anOutFile [open "$aGuidsFilePath" "w"]
564   fconfigure $anOutFile -translation lf
565   foreach aKey [array names ::THE_GUIDS_LIST] {
566     set aValue $::THE_GUIDS_LIST($aKey)
567     puts $anOutFile "${aKey}=${aValue}"
568   }
569   close $anOutFile
570 }
571
572 # Function to generate Visual Studio solution and project files
573 proc OS:MKVC { theOutDir theModules theTools theAllSolution theVcVer isUWP } {
574
575   puts stderr "Generating VS project files for $theVcVer"
576
577   # generate projects for toolkits and separate solution for each module
578   foreach aModule $theModules {
579     OS:vcsolution $theVcVer $aModule $aModule $theOutDir ::THE_GUIDS_LIST "src" "" ""
580     OS:vcproj     $theVcVer $isUWP   $aModule $theOutDir ::THE_GUIDS_LIST "src"    ""
581   }
582
583   # generate projects for toolkits and separate solution for each tool
584   foreach aTool $theTools {
585     OS:vcsolution $theVcVer $aTool $aTool $theOutDir ::THE_GUIDS_LIST "tools" "" "src"
586     OS:vcproj     $theVcVer $isUWP $aTool $theOutDir ::THE_GUIDS_LIST "tools"    "src"
587   }
588
589   # generate single solution "OCCT" containing projects from all modules
590   if { "$theAllSolution" != "" } {
591     OS:vcsolution $theVcVer $theAllSolution $theModules $theOutDir ::THE_GUIDS_LIST "src" $theTools "tools"
592   }
593
594   puts "The Visual Studio solution and project files are stored in the $theOutDir directory"
595 }
596
597 proc OS:init {theNameOfDefFile {os {}}} {
598   set askplat $os
599   set aModules {}
600   if { "$os" == "" } {
601     set os $::tcl_platform(os)
602   }
603
604   # Load list of OCCT modules and their definitions
605   source "$::path/src/OS/${theNameOfDefFile}.tcl"
606   foreach aModuleIter [OS:Modules] {
607     set aFileTcl "$::path/src/OS/${aModuleIter}.tcl"
608     if [file exists $aFileTcl] {
609       source $aFileTcl
610       lappend aModules $aModuleIter
611     } else {
612       puts stderr "Definition file for $aModuleIter is not found in unit OS"
613     }
614   }
615
616   return $aModules
617 }
618
619 # topological sort. returns a list {  {a h} {b g} {c f} {c h} {d i}  } => { d a b c i g f h }
620 proc wokUtils:EASY:tsort { listofpairs } {
621     foreach x $listofpairs {
622         set e1 [lindex $x 0]
623         set e2 [lindex $x 1]
624         if ![info exists pcnt($e1)] {
625             set pcnt($e1) 0
626         }
627         if ![ info exists pcnt($e2)] {
628             set pcnt($e2) 1
629         } else {
630             incr pcnt($e2)
631         }
632         if ![info exists scnt($e1)] {
633             set scnt($e1) 1
634         } else {
635             incr scnt($e1)
636         }
637         set l {}
638         if [info exists slist($e1)] {
639             set l $slist($e1)
640         }
641         lappend l $e2
642         set slist($e1) $l
643     }
644     set nodecnt 0
645     set back 0
646     foreach node [array names pcnt] {
647         incr nodecnt
648         if { $pcnt($node) == 0 } {
649             incr back
650             set q($back) $node
651         }
652         if ![info exists scnt($node)] {
653             set scnt($node) 0
654         }
655     }
656     set res {}
657     for {set front 1} { $front <= $back } { incr front } {
658         lappend res [set node $q($front)]
659         for {set i 1} {$i <= $scnt($node) } { incr i } {
660             set ll $slist($node)
661             set j [expr {$i - 1}]
662             set u [expr { $pcnt([lindex $ll $j]) - 1 }]
663             if { [set pcnt([lindex $ll $j]) $u] == 0 } {
664                 incr back
665                 set q($back) [lindex $ll $j]
666             }
667         }
668     }
669     if { $back != $nodecnt } {
670         puts stderr "input contains a cycle"
671         return {}
672     } else {
673         return $res
674     }
675 }
676
677 proc wokUtils:LIST:Purge { l } {
678     set r {}
679      foreach e $l {
680          if ![info exist tab($e)] {
681              lappend r $e
682              set tab($e) {}
683          } 
684      }
685      return $r
686 }
687
688 # Read file pointed to by path
689 # 1. sort = 1 tri 
690 # 2. trim = 1 plusieurs blancs => 1 seul blanc
691 # 3. purge= not yet implemented.
692 # 4. emptl= dont process blank lines
693 proc wokUtils:FILES:FileToList { path {sort 0} {trim 0} {purge 0} {emptl 1} } {
694     if ![ catch { set id [ open $path r ] } ] {
695         set l  {}
696         while {[gets $id line] >= 0 } {
697             if { $trim } {
698                 regsub -all {[ ]+} $line " " line
699             }
700             if { $emptl } {
701                 if { [string length ${line}] != 0 } {
702                     lappend l $line
703                 }
704             } else {
705                 lappend l $line
706             }
707         }
708         close $id
709         if { $sort } {
710             return [lsort $l]
711         } else {
712             return $l
713         }
714     } else {
715         return {}
716     }
717 }
718
719 # retorn the list of executables in module.
720 proc OS:executable { module } {
721     set lret {}
722     foreach XXX  [${module}:ressources] {
723         if { "[lindex $XXX 1]" == "x" } {
724             lappend lret [lindex $XXX 2]
725         }
726     }
727     return $lret
728 }
729
730 # Topological sort of toolkits in tklm
731 proc osutils:tk:sort { tklm theSrcDir theSourceDirOther } {
732   set tkby2 {}
733   foreach tkloc $tklm {
734     set lprg [wokUtils:LIST:Purge [osutils:tk:close $tkloc $theSrcDir $theSourceDirOther]]
735     foreach tkx  $lprg {
736       if { [lsearch $tklm $tkx] != -1 } {
737         lappend tkby2 [list $tkx $tkloc]
738       } else {
739         lappend tkby2 [list $tkloc {}]
740       }
741     }
742   }
743   set lret {}
744   foreach e [wokUtils:EASY:tsort $tkby2] {
745     if { $e != {} } {
746       lappend lret $e
747     }
748   }
749   return $lret
750 }
751
752 #  close dependencies of ltk. (full wok pathes of toolkits)
753 # The CURRENT WOK LOCATION MUST contains ALL TOOLKITS required.
754 # (locate not performed.)
755 proc osutils:tk:close { ltk theSrcDir theSourceDirOther } {
756   set result {}
757   set recurse {}
758   foreach dir $ltk {
759     set ids [LibToLink $dir $theSrcDir $theSourceDirOther]
760 #    puts "osutils:tk:close($ltk) ids='$ids'"
761     set eated [osutils:tk:eatpk $ids]
762     set result [concat $result $eated]
763     set ids [LibToLink $dir $theSrcDir $theSourceDirOther]
764     set result [concat $result $ids]
765
766     foreach file $eated {
767       set kds [osutils:findSrcSubPath $theSrcDir "$file/EXTERNLIB"]
768       if { [osutils:tk:eatpk $kds] !=  {} } {
769         lappend recurse $file
770       }
771     }
772   }
773   if { $recurse != {} } {
774     set result [concat $result [osutils:tk:close $recurse $theSrcDir $theSourceDirOther]]
775   }
776   return $result
777 }
778
779 proc osutils:tk:eatpk { EXTERNLIB  } {
780   set l [wokUtils:FILES:FileToList $EXTERNLIB]
781   set lret  {}
782   foreach str $l {
783     if ![regexp -- {(CSF_[^ ]*)} $str csf] {
784       lappend lret $str
785     }
786   }
787   return $lret
788 }
789 # Define libraries to link using only EXTERNLIB file
790
791 proc LibToLink {theTKit theSrcDir theSourceDirOther} {
792   regexp {^.*:([^:]+)$} $theTKit dummy theTKit
793   set type [_get_type $theTKit]
794   if {$type != "t" && $type != "x"} {
795     return
796   }
797   set aToolkits {}
798   set anExtLibList [osutils:tk:eatpk [osutils:findSrcSubPath $theSrcDir "$theTKit/EXTERNLIB"]]
799   foreach anExtLib $anExtLibList {
800     set aFullPath [LocateRecur $anExtLib $theSrcDir]
801     if { "$aFullPath" == "" && "$theSourceDirOther" != "" } {
802       set aFullPath [LocateRecur $anExtLib $theSourceDirOther]
803     }
804     if { "$aFullPath" != "" && [_get_type $anExtLib] == "t" } {
805       lappend aToolkits $anExtLib
806     }
807   }
808   return $aToolkits
809 }
810 # Search unit recursively
811
812 proc LocateRecur {theName theSrcDir} {
813   set theNamePath [osutils:findSrcSubPath $theSrcDir "$theName"]
814   if {[file isdirectory $theNamePath]} {
815     return $theNamePath
816   }
817   return ""
818 }
819
820 proc OS:genGUID { {theFormat "vc"} } {
821   if { "$theFormat" == "vc" } {
822     set p1 "[format %07X [expr { int(rand() * 268435456) }]][format %X [expr { int(rand() * 16) }]]"
823     set p2 "[format %04X [expr { int(rand() * 6536) }]]"
824     set p3 "[format %04X [expr { int(rand() * 6536) }]]"
825     set p4 "[format %04X [expr { int(rand() * 6536) }]]"
826     set p5 "[format %06X [expr { int(rand() * 16777216) }]][format %06X [expr { int(rand() * 16777216) }]]"
827     return "{$p1-$p2-$p3-$p4-$p5}"
828   } else {
829     set p1 "[format %04X [expr { int(rand() * 6536) }]]"
830     set p2 "[format %04X [expr { int(rand() * 6536) }]]"
831     set p3 "[format %04X [expr { int(rand() * 6536) }]]"
832     set p4 "[format %04X [expr { int(rand() * 6536) }]]"
833     set p5 "[format %04X [expr { int(rand() * 6536) }]]"
834     set p6 "[format %04X [expr { int(rand() * 6536) }]]"
835     return "$p1$p2$p3$p4$p5$p6"
836   }
837 }
838
839 # collect all include file that required for theModules in theOutDir
840 proc osutils:collectinc {theModules theSrcDir theIncPath} {
841   global path
842   set aCasRoot [file normalize $path]
843   set anIncPath [file normalize $theIncPath]
844
845   if {![file isdirectory $aCasRoot]} {
846     puts "OCCT directory is not defined correctly: $aCasRoot"
847     return
848   }
849
850   set anUsedToolKits {}
851   foreach aModule $theModules {
852     foreach aToolKit [${aModule}:toolkits] {
853       lappend anUsedToolKits $aToolKit
854
855       foreach aDependency [LibToLink $aToolKit $theSrcDir ""] {
856         lappend anUsedToolKits $aDependency
857       }
858     }
859     foreach anExecutable [OS:executable ${aModule}] {
860       lappend anUsedToolKits $anExecutable
861
862       foreach aDependency [LibToLink $anExecutable $theSrcDir ""] {
863         lappend anUsedToolKits $aDependency
864       }
865     }
866   }
867   set anUsedToolKits [lsort -unique $anUsedToolKits]
868
869   set anUnits {}
870   foreach anUsedToolKit $anUsedToolKits {
871     set anUnits [concat $anUnits [osutils:tk:units $anUsedToolKit $theSrcDir] ]
872   }
873   set anUnits [lsort -unique $anUnits]
874
875   # define copying style
876   set aCopyType "copy"
877   if { [info exists ::env(SHORTCUT_HEADERS)] } {
878     if { [string equal -nocase $::env(SHORTCUT_HEADERS) "hard"]
879       || [string equal -nocase $::env(SHORTCUT_HEADERS) "hardlink"] } {
880       set aCopyType "hardlink"
881     } elseif { [string equal -nocase $::env(SHORTCUT_HEADERS) "true"]
882             || [string equal -nocase $::env(SHORTCUT_HEADERS) "shortcut"] } {
883       set aCopyType "shortcut"
884     }
885   }
886
887   set allHeaderFiles {}
888   if { $aCopyType == "shortcut" } {
889     # template preparation
890     if { ![file exists $::THE_CASROOT/adm/templates/header.in] } {
891       puts "template file does not exist: $::THE_CASROOT/adm/templates/header.in"
892       return
893     }
894     set aHeaderTmpl [wokUtils:FILES:FileToString $::THE_CASROOT/adm/templates/header.in]
895
896     # relative anIncPath in connection with aCasRoot/$theSrcDir
897     set aFromBuildIncToSrcPath [relativePath "$anIncPath" "$aCasRoot/$theSrcDir"]
898
899     # create and copy short-cut header files
900     foreach anUnit $anUnits {
901       osutils:checksrcfiles ${anUnit} $theSrcDir
902
903       set aHFiles [_get_used_files ${anUnit} $theSrcDir true false]
904       foreach aHeaderFile ${aHFiles} {
905         set aHeaderFileName [lindex ${aHeaderFile} 1]
906         lappend allHeaderFiles "${aHeaderFileName}"
907
908         regsub -all -- {@OCCT_HEADER_FILE_CONTENT@} $aHeaderTmpl "#include \"$aFromBuildIncToSrcPath/$anUnit/$aHeaderFileName\"" aShortCutHeaderFileContent
909
910         if {[file exists "$theIncPath/$aHeaderFileName"] && [file readable "$theIncPath/$aHeaderFileName"]} {
911           set fp [open "$theIncPath/$aHeaderFileName" r]
912           set aHeaderContent [read $fp]
913           close $fp
914
915           # minus eof
916           set aHeaderLenght  [expr [string length $aHeaderContent] - 1]
917
918           if {$aHeaderLenght == [string length $aShortCutHeaderFileContent]} {
919             # remove eof from string
920             set aHeaderContent [string range $aHeaderContent 0 [expr $aHeaderLenght - 1]]
921
922             if {[string compare $aShortCutHeaderFileContent $aHeaderContent] == 0} {
923               continue
924             }
925           }
926           file delete -force "$theIncPath/$aHeaderFileName"
927         }
928
929         set aShortCutHeaderFile [open "$theIncPath/$aHeaderFileName" "w"]
930         fconfigure $aShortCutHeaderFile -translation lf
931         puts $aShortCutHeaderFile $aShortCutHeaderFileContent
932         close $aShortCutHeaderFile
933       }
934     }
935   } else {
936     set nbcopied 0
937     foreach anUnit $anUnits {
938       osutils:checksrcfiles ${anUnit} $theSrcDir
939
940       set aHFiles [_get_used_files ${anUnit} $theSrcDir true false]
941       foreach aHeaderFile ${aHFiles} {
942         set aHeaderFileName [lindex ${aHeaderFile} 1]
943         lappend allHeaderFiles "${aHeaderFileName}"
944
945         # copy file only if target does not exist or is older than original
946         set torig [file mtime $aCasRoot/$theSrcDir/$anUnit/$aHeaderFileName]
947         set tcopy 0
948         if { [file isfile $anIncPath/$aHeaderFileName] } {
949           set tcopy [file mtime $anIncPath/$aHeaderFileName]
950         }
951         if { $tcopy < $torig } {
952           incr nbcopied
953           if { $aCopyType == "hardlink" } {
954             if { $tcopy != 0 } {
955               file delete -force "$theIncPath/$aHeaderFileName"
956             }
957             file link -hard  $anIncPath/$aHeaderFileName $aCasRoot/$theSrcDir/$anUnit/$aHeaderFileName
958           } else {
959             file copy -force $aCasRoot/$theSrcDir/$anUnit/$aHeaderFileName $anIncPath/$aHeaderFileName
960           }
961         } elseif { $tcopy != $torig } {
962           puts "Warning: file $anIncPath/$aHeaderFileName is newer than $aCasRoot/$theSrcDir/$anUnit/$aHeaderFileName, not changed!"
963         }
964       }
965     }
966     puts "Info: $nbcopied files updated"
967   }
968
969   # remove header files not listed in FILES
970   set anIncFiles [glob -tails -nocomplain -dir ${anIncPath} "*"]
971   foreach anIncFile ${anIncFiles} {
972     if { [lsearch -exact ${allHeaderFiles} ${anIncFile}] == -1 } {
973       puts "Warning: file ${anIncPath}/${anIncFile} is not present in the sources and will be removed from ${theIncPath}"
974       file delete -force "${theIncPath}/${anIncFile}"
975     }
976   }
977 }
978
979 # Generate header for VS solution file
980 proc osutils:vcsolution:header { vcversion } {
981   if { "$vcversion" == "vc7" } {
982     append var \
983       "Microsoft Visual Studio Solution File, Format Version 8.00\n"
984   } elseif { "$vcversion" == "vc8" } {
985     append var \
986       "Microsoft Visual Studio Solution File, Format Version 9.00\n" \
987       "# Visual Studio 2005\n"
988   } elseif { "$vcversion" == "vc9" } {
989     append var \
990       "Microsoft Visual Studio Solution File, Format Version 10.00\n" \
991       "# Visual Studio 2008\n"
992   } elseif { "$vcversion" == "vc10" } {
993     append var \
994       "Microsoft Visual Studio Solution File, Format Version 11.00\n" \
995       "# Visual Studio 2010\n"
996   } elseif { "$vcversion" == "vc11" } {
997     append var \
998       "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
999       "# Visual Studio 2012\n"
1000   } elseif { "$vcversion" == "vc12" } {
1001     append var \
1002       "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
1003       "# Visual Studio 2013\n"
1004   } elseif { "$vcversion" == "vc14" || "$vcversion" == "vc141" || 
1005              "$vcversion" == "vc142" || "$vcversion" == "vclang" } {
1006     append var \
1007       "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
1008       "# Visual Studio 14\n"
1009   } else {
1010     puts stderr "Error: Visual Studio version $vcversion is not supported by this function!"
1011   }
1012   return $var
1013 }
1014 # Returns extension (without dot) for project files of given version of VC
1015
1016 proc osutils:vcproj:ext { vcversion } {
1017   if { "$vcversion" == "vc7" || "$vcversion" == "vc8" || "$vcversion" == "vc9" } {
1018     return "vcproj"
1019   } else {
1020     return "vcxproj"
1021   }
1022 }
1023 # Generate start of configuration section of VS solution file
1024
1025 proc osutils:vcsolution:config:begin { vcversion } {
1026   if { "$vcversion" == "vc7" } {
1027     append var \
1028       "Global\n" \
1029       "\tGlobalSection(SolutionConfiguration) = preSolution\n" \
1030       "\t\tDebug = Debug\n" \
1031       "\t\tRelease = Release\n" \
1032       "\tEndGlobalSection\n" \
1033       "\tGlobalSection(ProjectConfiguration) = postSolution\n"
1034   } else {
1035     append var \
1036       "Global\n" \
1037       "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n" \
1038       "\t\tDebug|Win32 = Debug|Win32\n" \
1039       "\t\tRelease|Win32 = Release|Win32\n" \
1040       "\t\tDebug|x64 = Debug|x64\n" \
1041       "\t\tRelease|x64 = Release|x64\n" \
1042       "\tEndGlobalSection\n" \
1043       "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"
1044   }
1045   return $var
1046 }
1047 # Generate part of configuration section of VS solution file describing one project
1048
1049 proc osutils:vcsolution:config:project { vcversion guid } {
1050   if { "$vcversion" == "vc7" } {
1051     append var \
1052       "\t\t$guid.Debug.ActiveCfg = Debug|Win32\n" \
1053       "\t\t$guid.Debug.Build.0 = Debug|Win32\n" \
1054       "\t\t$guid.Release.ActiveCfg = Release|Win32\n" \
1055       "\t\t$guid.Release.Build.0 = Release|Win32\n"
1056   } else {
1057     append var \
1058       "\t\t$guid.Debug|Win32.ActiveCfg = Debug|Win32\n" \
1059       "\t\t$guid.Debug|Win32.Build.0 = Debug|Win32\n" \
1060       "\t\t$guid.Release|Win32.ActiveCfg = Release|Win32\n" \
1061       "\t\t$guid.Release|Win32.Build.0 = Release|Win32\n" \
1062       "\t\t$guid.Debug|x64.ActiveCfg = Debug|x64\n" \
1063       "\t\t$guid.Debug|x64.Build.0 = Debug|x64\n" \
1064       "\t\t$guid.Release|x64.ActiveCfg = Release|x64\n" \
1065       "\t\t$guid.Release|x64.Build.0 = Release|x64\n"
1066   }
1067   return $var
1068 }
1069 # Generate start of configuration section of VS solution file
1070
1071 proc osutils:vcsolution:config:end { vcversion } {
1072   if { "$vcversion" == "vc7" } {
1073     append var \
1074       "\tEndGlobalSection\n" \
1075       "\tGlobalSection(ExtensibilityGlobals) = postSolution\n" \
1076       "\tEndGlobalSection\n" \
1077       "\tGlobalSection(ExtensibilityAddIns) = postSolution\n" \
1078       "\tEndGlobalSection\n"
1079   } else {
1080     append var \
1081       "\tEndGlobalSection\n" \
1082       "\tGlobalSection(SolutionProperties) = preSolution\n" \
1083       "\t\tHideSolutionNode = FALSE\n" \
1084       "\tEndGlobalSection\n"
1085   }
1086   return $var
1087 }
1088 # generate Visual Studio solution file
1089 # if module is empty, generates one solution for all known modules
1090
1091 proc OS:vcsolution { theVcVer theSolName theModules theOutDir theGuidsMap theSrcDir theModulesOther theSourceDirOther } {
1092   global path
1093   upvar $theGuidsMap aGuidsMap
1094
1095   # collect list of projects to be created
1096   set aProjects {}
1097   set aDependencies {}
1098
1099   osutils:convertModules $theModules $theSrcDir $theSourceDirOther aProjects aProjectsInModule aDependencies
1100   osutils:convertModules $theModulesOther $theSourceDirOther $theSrcDir aProjects aProjectsInModule aDependencies
1101
1102 # generate GUIDs for projects (unless already known)
1103   foreach aProject $aProjects {
1104     if { ! [info exists aGuidsMap($aProject)] } {
1105       set aGuidsMap($aProject) [OS:genGUID]
1106     }
1107   }
1108
1109   # generate solution file
1110 #  puts "Generating Visual Studio ($theVcVer) solution file for $theSolName ($aProjects)"
1111   append aFileBuff [osutils:vcsolution:header $theVcVer]
1112
1113   # GUID identifying group projects in Visual Studio
1114   set VC_GROUP_GUID "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"
1115
1116   # generate group projects -- one per module
1117   if { "$theVcVer" != "vc7" && [llength "$theModules"] > 1 } {
1118     foreach aModule $theModules {
1119       if { ! [info exists aGuidsMap(_$aModule)] } {
1120         set aGuidsMap(_$aModule) [OS:genGUID]
1121       }
1122       set aGuid $aGuidsMap(_$aModule)
1123       append aFileBuff "Project(\"${VC_GROUP_GUID}\") = \"$aModule\", \"$aModule\", \"$aGuid\"\nEndProject\n"
1124     }
1125   }
1126
1127   if { "$theVcVer" != "vc7" && [llength "$theModulesOther"] > 1 } {
1128     set aModule "Tools"
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   # extension of project files
1137   set aProjExt [osutils:vcproj:ext $theVcVer]
1138
1139   # GUID identifying C++ projects in Visual Studio
1140   set VC_CPP_GUID "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"
1141
1142   # generate normal projects
1143   set aProjsNb [llength $aProjects]
1144   for {set aProjId 0} {$aProjId < $aProjsNb} {incr aProjId} {
1145     set aProj [lindex $aProjects $aProjId]
1146     set aGuid $aGuidsMap($aProj)
1147     append aFileBuff "Project(\"${VC_CPP_GUID}\") = \"$aProj\", \"$aProj.${aProjExt}\", \"$aGuid\"\n"
1148     # write projects dependencies information (vc7 to vc9)
1149     set aDepGuids ""
1150     foreach aDepLib [lindex $aDependencies $aProjId] {
1151       if { $aDepLib != $aProj && [lsearch $aProjects $aDepLib] != "-1" } {
1152         set depGUID $aGuidsMap($aDepLib)
1153         append aDepGuids "\t\t$depGUID = $depGUID\n"
1154       }
1155     }
1156     if { "$aDepGuids" != "" } {
1157       append aFileBuff "\tProjectSection(ProjectDependencies) = postProject\n"
1158       append aFileBuff "$aDepGuids"
1159       append aFileBuff "\tEndProjectSection\n"
1160     }
1161     append aFileBuff "EndProject\n"
1162   }
1163
1164   # generate configuration section
1165   append aFileBuff [osutils:vcsolution:config:begin $theVcVer]
1166   foreach aProj $aProjects {
1167     append aFileBuff [osutils:vcsolution:config:project $theVcVer $aGuidsMap($aProj)]
1168   }
1169   append aFileBuff [osutils:vcsolution:config:end $theVcVer]
1170
1171   # write information of grouping of projects by module
1172   if { "$theVcVer" != "vc7" && [llength "$theModules"] > 1 } {
1173     append aFileBuff "  GlobalSection(NestedProjects) = preSolution\n"
1174     foreach aModule $theModules {
1175       if { ! [info exists aProjectsInModule($aModule)] } { continue }
1176       foreach aProject $aProjectsInModule($aModule) {
1177         append aFileBuff "              $aGuidsMap($aProject) = $aGuidsMap(_$aModule)\n"
1178       }
1179     }
1180     set aToolsName "Tools"
1181     foreach aModule $theModulesOther {
1182       if { ! [info exists aProjectsInModule($aModule)] } { continue }
1183       foreach aProject $aProjectsInModule($aModule) {
1184         append aFileBuff "              $aGuidsMap($aProject) = $aGuidsMap(_$aToolsName)\n"
1185       }
1186     }
1187     append aFileBuff "  EndGlobalSection\n"
1188   }
1189
1190   # final word (footer)
1191   append aFileBuff "EndGlobal"
1192
1193   # write solution
1194   set aFile [open [set fdsw [file join $theOutDir ${theSolName}.sln]] w]
1195   fconfigure $aFile -translation crlf
1196   puts $aFile $aFileBuff
1197   close $aFile
1198   return [file join $theOutDir ${theSolName}.sln]
1199 }
1200
1201 # Generate auxiliary containers with information about modules.
1202 # @param theModules List of modules       
1203 # @param theSrcDir Directory of module toolkits
1204 # @param theSourceDirOther Directory with other additional sources to find out toolkits in dependencies
1205 # @param theProjects list of all found projects/toolkits
1206 # @param theProjectsInModule map of module into toolkits/projects
1207 # @param theDependencies list of the project dependencies. To find the project dependencies, get it by the index in project container
1208 proc osutils:convertModules { theModules theSrcDir theSourceDirOther theProjects theProjectsInModule theDependencies } {
1209   global path
1210   upvar $theProjectsInModule aProjectsInModule
1211   upvar $theProjects aProjects
1212   upvar $theDependencies aDependencies
1213
1214   foreach aModule $theModules {
1215     # toolkits
1216     foreach aToolKit [osutils:tk:sort [${aModule}:toolkits] $theSrcDir $theSourceDirOther] {
1217       lappend aProjects $aToolKit
1218       lappend aProjectsInModule($aModule) $aToolKit
1219       lappend aDependencies [LibToLink $aToolKit $theSrcDir $theSourceDirOther]
1220     }
1221     # executables, assume one project per cxx file...
1222     foreach aUnit [OS:executable ${aModule}] {
1223       set aUnitLoc $aUnit
1224       set src_files [_get_used_files $aUnit $theSrcDir false]
1225       set aSrcFiles {}
1226       foreach s $src_files {
1227         regexp {source ([^\s]+)} $s dummy name
1228         lappend aSrcFiles $name
1229       }
1230       foreach aSrcFile $aSrcFiles {
1231         set aFileExtension [file extension $aSrcFile]
1232         if { $aFileExtension == ".cxx" } {
1233           set aPrjName [file rootname $aSrcFile]
1234           lappend aProjects $aPrjName
1235           lappend aProjectsInModule($aModule) $aPrjName
1236           if {[file isdirectory $path/$theSrcDir/$aUnitLoc]} {
1237             lappend aDependencies [LibToLinkX $aUnitLoc [file rootname $aSrcFile] $theSrcDir $theSourceDirOther]
1238           } else {
1239             lappend aDependencies {}
1240           }
1241         }
1242       }
1243     }
1244   }
1245 }
1246 # Generate Visual Studio projects for specified version
1247
1248 proc OS:vcproj { theVcVer isUWP theModules theOutDir theGuidsMap theSrcDir theSourceDirOther } {
1249   upvar $theGuidsMap aGuidsMap
1250
1251   set aProjectFiles {}
1252
1253   foreach aModule $theModules {
1254     foreach aToolKit [${aModule}:toolkits] {
1255       lappend aProjectFiles [osutils:vcproj  $theVcVer $isUWP $theOutDir $aToolKit     aGuidsMap $theSrcDir $theSourceDirOther]
1256     }
1257     foreach anExecutable [OS:executable ${aModule}] {
1258       lappend aProjectFiles [osutils:vcprojx $theVcVer $isUWP $theOutDir $anExecutable aGuidsMap $theSrcDir $theSourceDirOther]
1259     }
1260   }
1261   return $aProjectFiles
1262 }
1263 # generate template name and load it for given version of Visual Studio and platform
1264
1265 proc osutils:vcproj:readtemplate {theVcVer isUWP isExec} {
1266   set anExt $theVcVer
1267   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1268     set anExt vc10
1269   }
1270
1271   # determine versions of runtime and toolset
1272   set aVCRTVer $theVcVer 
1273   set aToolset "v[string range $theVcVer 2 3]0"
1274   if { $theVcVer == "vc141" } {
1275     set aVCRTVer "vc14"
1276     set aToolset "v141"
1277   } elseif { $theVcVer == "vc142" } {
1278     set aVCRTVer "vc14"
1279     set aToolset "v142"
1280   } elseif { $theVcVer == "vclang" } {
1281     set aVCRTVer "vc14"
1282     set aToolset "ClangCL"
1283   }
1284
1285   set what "$theVcVer"
1286   set aCmpl32 ""
1287   set aCmpl64 ""
1288   set aCharSet "Unicode"
1289   if { $isExec } {
1290     set anExt "${anExt}x"
1291     set what "$what executable"
1292   }
1293   if { "$theVcVer" == "vc10" } {
1294     # SSE2 is enabled by default in vc11+, but not in vc10 for 32-bit target
1295     set aCmpl32 "<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>"
1296   }
1297   set aTmpl [osutils:readtemplate $anExt "MS VC++ project ($what)"]
1298
1299   if { $isUWP } {
1300     set UwpWinRt "<CompileAsWinRT>false</CompileAsWinRT>"
1301     foreach bitness {32 64} {
1302       set indent ""
1303       if {"[set aCmpl${bitness}]" != ""} {
1304         set indent "\n      "
1305       }
1306       set aCmpl${bitness} "[set aCmpl${bitness}]${indent}${UwpWinRt}"
1307     }
1308   }
1309
1310   set format_template "\[\\r\\n\\s\]*"
1311   foreach bitness {32 64} {
1312     set format_templateloc ""
1313     if {"[set aCmpl${bitness}]" == ""} {
1314       set format_templateloc "$format_template"
1315     }
1316     regsub -all -- "${format_templateloc}__VCMPL${bitness}__" $aTmpl "[set aCmpl${bitness}]" aTmpl
1317   }
1318
1319   set aDebugInfo "no"
1320   set aReleaseLnk ""
1321   if { "$::HAVE_RelWithDebInfo" == "true" } {
1322     set aDebugInfo "true"
1323     set aReleaseLnk "\n      <OptimizeReferences>true</OptimizeReferences>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>"
1324   }
1325
1326   regsub -all -- {__VCVER__}     $aTmpl $aVCRTVer aTmpl
1327   regsub -all -- {__VCVEREXT__}  $aTmpl $aToolset aTmpl
1328   regsub -all -- {__VCCHARSET__} $aTmpl $aCharSet aTmpl
1329   regsub -all -- {__VCReleasePDB__} $aTmpl $aDebugInfo aTmpl
1330   regsub -all -- "${format_template}__VCLNKREL__" $aTmpl "${aReleaseLnk}" aTmpl
1331
1332   return $aTmpl
1333 }
1334
1335 proc osutils:readtemplate {ext what} {
1336   set loc "$::THE_CASROOT/adm/templates/template.$ext"
1337   return [wokUtils:FILES:FileToString $loc]
1338 }
1339 # Read a file in a string as is.
1340
1341 proc wokUtils:FILES:FileToString { fin } {
1342     if { [catch { set in [ open $fin r ] } errin] == 0 } {
1343         set strin [read $in [file size $fin]]
1344         close $in
1345         return $strin
1346     } else {
1347         return {}
1348     }
1349 }
1350
1351 # List extensions of compilable files in OCCT
1352 proc osutils:compilable {thePlatform} {
1353   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } { return [list .c .cxx .cpp .mm] }
1354   return [list .c .cxx .cpp]
1355 }
1356
1357 # List extensions of header file in OCCT
1358 proc osutils:fileExtensionsHeaders {thePlatform} {
1359   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } { return [list .h .hxx .hpp .lxx .pxx .gxx ] }
1360   return [list .h .hxx .hpp .lxx .pxx .gxx .mm ]
1361 }
1362
1363 # List extensions of Qt resource file in OCCT
1364 proc osutils:fileExtensionsResources {thePlatform} {
1365   return [list .qrc ]
1366 }
1367
1368 proc osutils:commonUsedTK { theToolKit theSrcDir theSourceDirOther} {
1369   set anUsedToolKits [list]
1370   set aDepToolkits [LibToLink $theToolKit $theSrcDir $theSourceDirOther]
1371   foreach tkx $aDepToolkits {
1372     if {[_get_type $tkx] == "t"} {
1373       lappend anUsedToolKits "${tkx}"
1374     }
1375   }
1376   return $anUsedToolKits
1377 }
1378
1379 # Return the list of name *CSF_ in a EXTERNLIB description of a toolkit
1380 proc osutils:tk:csfInExternlib { EXTERNLIB } {
1381   set l [wokUtils:FILES:FileToList $EXTERNLIB]
1382   set lret  {STLPort}
1383   foreach str $l {
1384     if [regexp -- {(CSF_[^ ]*)} $str csf] {
1385       lappend lret $csf
1386     }
1387   }
1388   return $lret
1389 }
1390
1391 # Collect dependencies map depending on target OS (libraries for CSF_ codenames used in EXTERNLIB) .
1392 # @param theOS         - target OS
1393 # @param theCsfLibsMap - libraries  map
1394 # @param theCsfFrmsMap - frameworks map, OS X specific
1395 proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap theRelease} {
1396   upvar $theCsfLibsMap aLibsMap
1397   upvar $theCsfFrmsMap aFrmsMap
1398
1399   unset theCsfLibsMap
1400   unset theCsfFrmsMap
1401
1402   set aLibsMap(CSF_FREETYPE)  "freetype"
1403   set aLibsMap(CSF_TclLibs)   "tcl8.6"
1404   set aLibsMap(CSF_TclTkLibs) "tk8.6"
1405   if { "$::HAVE_FREEIMAGE" == "true" } {
1406     if { "$theOS" == "wnt" } {
1407       set aLibsMap(CSF_FreeImagePlus) "FreeImage"
1408     } else {
1409       set aLibsMap(CSF_FreeImagePlus) "freeimage"
1410     }
1411   } elseif { "$theOS" == "wnt" } {
1412     set aLibsMap(CSF_FreeImagePlus) "windowscodecs"
1413   }
1414   if { "$::HAVE_FFMPEG" == "true" } {
1415     set aLibsMap(CSF_FFmpeg) "avcodec avformat swscale avutil"
1416   }
1417   if { "$::HAVE_TBB" == "true" } {
1418     set aLibsMap(CSF_TBB) "tbb tbbmalloc"
1419   }
1420   if { "$::HAVE_VTK" == "true" } {
1421     if { "$theOS" == "wnt" } {
1422       set aLibsMap(CSF_VTK) [osutils:vtkCsf "wnt"]
1423     } else {
1424       set aLibsMap(CSF_VTK) [osutils:vtkCsf "unix"]
1425     }
1426   }
1427   if { "$::HAVE_ZLIB" == "true" } {
1428     set aLibsMap(CSF_ZLIB) "z"
1429   }
1430   if { "$::HAVE_LIBLZMA" == "true" } {
1431     set aLibsMap(CSF_LIBLZMA) "liblzma"
1432   }
1433   if { "$::HAVE_E57" == "true" && "$theOS" != "wnt" } {
1434     # exclude wnt, as there are different pragma lib depending on debug/release
1435     set aLibsMap(CSF_E57)    "E57RefImpl"
1436     set aLibsMap(CSF_xerces) "xerces-c"
1437   }
1438
1439   if { "$theOS" == "wnt" } {
1440     #  WinAPI libraries
1441     set aLibsMap(CSF_kernel32)     "kernel32"
1442     set aLibsMap(CSF_advapi32)     "advapi32"
1443     set aLibsMap(CSF_gdi32)        "gdi32"
1444     set aLibsMap(CSF_user32)       "user32 comdlg32"
1445     set aLibsMap(CSF_shell32)      "shell32"
1446     set aLibsMap(CSF_opengl32)     "opengl32"
1447     set aLibsMap(CSF_wsock32)      "wsock32"
1448     set aLibsMap(CSF_netapi32)     "netapi32"
1449     set aLibsMap(CSF_winmm)        "winmm"
1450     set aLibsMap(CSF_OpenGlLibs)   "opengl32"
1451     if { "$::HAVE_GLES2" == "true" } {
1452       set aLibsMap(CSF_OpenGlLibs) "libEGL libGLESv2"
1453     }
1454     set aLibsMap(CSF_psapi)        "Psapi"
1455     set aLibsMap(CSF_d3d9)         "d3d9"
1456
1457     # the naming is different on Windows
1458     set aLibsMap(CSF_TclLibs)      "tcl86"
1459     set aLibsMap(CSF_TclTkLibs)    "tk86"
1460     if { "$theRelease" == "true" } {
1461       set aLibsMap(CSF_QT)         "Qt5Gui Qt5Widgets Qt5Xml Qt5Core"
1462     } else {
1463       set aLibsMap(CSF_QT)         "Qt5Guid Qt5Widgetsd Qt5Xmld Qt5Cored"
1464     }
1465
1466     # tbb headers define different pragma lib depending on debug/release
1467     set aLibsMap(CSF_TBB) ""
1468
1469     if { "$::HAVE_ZLIB" == "true" } {
1470       set aLibsMap(CSF_ZLIB) "zlib"
1471     }
1472   } else {
1473     set aLibsMap(CSF_dl)           "dl"
1474     if { "$theOS" == "mac" || "$theOS" == "ios" } {
1475       set aLibsMap(CSF_objc)       "objc"
1476       if { "$theOS" == "ios" } {
1477         set aFrmsMap(CSF_Appkit)     "UIKit"
1478         set aFrmsMap(CSF_OpenGlLibs) "OpenGLES"
1479       } else {
1480         set aFrmsMap(CSF_Appkit)     "AppKit"
1481         set aFrmsMap(CSF_OpenGlLibs) "OpenGL"
1482       }
1483       set aFrmsMap(CSF_IOKit)      "IOKit"
1484       set aFrmsMap(CSF_TclLibs)    "Tcl"
1485       set aLibsMap(CSF_TclLibs)    ""
1486       set aFrmsMap(CSF_TclTkLibs)  "Tk"
1487       set aLibsMap(CSF_TclTkLibs)  ""
1488       set aLibsMap(CSF_QT)         "QtCore QtGui"
1489     } elseif { "$theOS" == "android" } {
1490       set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1491       set aLibsMap(CSF_androidlog) "log"
1492     } else {
1493       set aLibsMap(CSF_fontconfig) "fontconfig"
1494       if { "$theOS" == "qnx" } {
1495         # CSF_ThreadLibs - pthread API is part of libc on QNX
1496         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1497       } else {
1498         set aLibsMap(CSF_ThreadLibs) "pthread rt"
1499         set aLibsMap(CSF_OpenGlLibs) "GL"
1500         set aLibsMap(CSF_TclTkLibs)  "X11 tk8.6"
1501         set aLibsMap(CSF_XwLibs)     "X11 Xext Xmu Xi"
1502         set aLibsMap(CSF_MotifLibs)  "X11"
1503       }
1504
1505       if { "$::HAVE_GLES2" == "true" } {
1506         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
1507       }
1508     }
1509   }
1510 }
1511
1512 # Returns string of library dependencies for generation of Visual Studio project or make lists.
1513 proc osutils:vtkCsf {{theOS ""}} {
1514   set aVtkVer "6.1"
1515
1516   set aPathSplitter ":"
1517   if {"$theOS" == "wnt"} {
1518     set aPathSplitter ";"
1519   }
1520
1521   set anOptIncs [split $::env(CSF_OPT_INC) "$aPathSplitter"]
1522   foreach anIncItem $anOptIncs {
1523     if {[regexp -- "vtk-(.*)$" [file tail $anIncItem] dummy aFoundVtkVer]} {
1524       set aVtkVer $aFoundVtkVer
1525     }
1526   }
1527
1528   set aLibArray [list vtkCommonCore vtkCommonDataModel vtkCommonExecutionModel vtkCommonMath vtkCommonTransforms vtkRenderingCore \
1529                       vtkRenderingOpenGL  vtkFiltersGeneral vtkIOCore vtkIOImage vtkImagingCore vtkInteractionStyle]
1530
1531   # Additional suffices for the libraries
1532   set anIdx 0
1533   foreach anItem $aLibArray {
1534     lset aLibArray $anIdx $anItem-$aVtkVer
1535     incr anIdx
1536   }
1537
1538   return [join $aLibArray " "]
1539 }
1540
1541 # @param theLibsList   - dependencies (libraries  list)
1542 # @param theFrameworks - dependencies (frameworks list, OS X specific)
1543 proc osutils:usedOsLibs { theToolKit theOS theLibsList theFrameworks theSrcDir { theRelease true } } {
1544   global path
1545   upvar $theLibsList   aLibsList
1546   upvar $theFrameworks aFrameworks
1547   set aLibsList   [list]
1548   set aFrameworks [list]
1549
1550   osutils:csfList $theOS aLibsMap aFrmsMap $theRelease
1551
1552   foreach aCsfElem [osutils:tk:csfInExternlib "$path/$theSrcDir/${theToolKit}/EXTERNLIB"] {
1553     if [info exists aLibsMap($aCsfElem)] {
1554       foreach aLib [split "$aLibsMap($aCsfElem)"] {
1555         if { [lsearch $aLibsList $aLib] == "-1" } {
1556           lappend aLibsList $aLib
1557         }
1558       }
1559     }
1560     if [info exists aFrmsMap($aCsfElem)] {
1561       foreach aFrm [split "$aFrmsMap($aCsfElem)"] {
1562         if { [lsearch $aFrameworks $aFrm] == "-1" } {
1563           lappend aFrameworks $aFrm
1564         }
1565       }
1566     }
1567   }
1568 }
1569
1570 # Returns liste of UD in a toolkit. tkloc is a full path wok.
1571 proc osutils:tk:units { tkloc theSrcDir } {
1572   global path
1573   set l {}
1574   set PACKAGES "$path/$theSrcDir/$tkloc/PACKAGES"
1575   foreach u [wokUtils:FILES:FileToList $PACKAGES] {
1576     if {[file isdirectory "$path/$theSrcDir/$u"]} {
1577       lappend l $u
1578     }
1579   }
1580   if { $l == {} } {
1581     ;#puts stderr "Warning. No devunit included in $tkloc"
1582   }
1583   return $l
1584 }
1585
1586 proc osutils:justwnt { listloc } {
1587   set goaway [list Xw]
1588   return [osutils:juststation $goaway $listloc]
1589 }
1590
1591 # remove from listloc OpenCascade units indesirables on NT
1592 proc osutils:juststation {goaway listloc} {
1593   global path
1594   set lret {}
1595   foreach u $listloc {
1596     if {([file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 )
1597      || (![file isdirectory "$path/src/$u"] && [lsearch $goaway $u] == -1 ) } {
1598       lappend lret $u
1599     }
1600   }
1601   return $lret
1602 }
1603
1604 # intersect3 - perform the intersecting of two lists, returning a list containing three lists.
1605 # The first list is everything in the first list that wasn't in the second,
1606 # the second list contains the intersection of the two lists, the third list contains everything
1607 # in the second list that wasn't in the first.
1608 proc osutils:intersect3 {list1 list2} {
1609   set la1(0) {} ; unset la1(0)
1610   set lai(0) {} ; unset lai(0)
1611   set la2(0) {} ; unset la2(0)
1612   foreach v $list1 {
1613     set la1($v) {}
1614   }
1615   foreach v $list2 {
1616     set la2($v) {}
1617   }
1618   foreach elem [concat $list1 $list2] {
1619     if {[info exists la1($elem)] && [info exists la2($elem)]} {
1620       unset la1($elem)
1621       unset la2($elem)
1622       set lai($elem) {}
1623     }
1624   }
1625   list [lsort [array names la1]] [lsort [array names lai]] [lsort [array names la2]]
1626 }
1627
1628 # Prepare relative path
1629 proc relativePath {thePathFrom thePathTo} {
1630   if { [file isdirectory "$thePathFrom"] == 0 } {
1631     return ""
1632   }
1633
1634   set aPathFrom [file normalize "$thePathFrom"]
1635   set aPathTo   [file normalize "$thePathTo"]
1636
1637   set aCutedPathFrom "${aPathFrom}/dummy"
1638   set aRelatedDeepPath ""
1639
1640   while { "$aCutedPathFrom" != [file normalize "$aCutedPathFrom/.."] } {
1641     set aCutedPathFrom [file normalize "$aCutedPathFrom/.."]
1642     # does aPathTo contain aCutedPathFrom?
1643     regsub -all $aCutedPathFrom $aPathTo "" aPathFromAfterCut
1644     if { "$aPathFromAfterCut" != "$aPathTo" } { # if so
1645       if { "$aCutedPathFrom" == "$aPathFrom" } { # just go higher, for example, ./somefolder/someotherfolder
1646         set aPathTo ".${aPathTo}"
1647       } elseif { "$aCutedPathFrom" == "$aPathTo" } { # remove the last "/"
1648         set aRelatedDeepPath [string replace $aRelatedDeepPath end end ""]
1649       }
1650       regsub -all $aCutedPathFrom $aPathTo $aRelatedDeepPath aPathToAfterCut
1651       regsub -all "//" $aPathToAfterCut "/" aPathToAfterCut
1652       return $aPathToAfterCut
1653     }
1654     set aRelatedDeepPath "$aRelatedDeepPath../"
1655
1656   }
1657
1658   return $thePathTo
1659 }
1660
1661 proc wokUtils:EASY:bs1 { s } {
1662     regsub -all {/} $s {\\} r
1663     return $r
1664 }
1665
1666 # Returs for a full path the liste of n last directory part
1667 # n = 1 => tail
1668 # n = 2 => dir/file.c
1669 # n = 3 => sdir/dir/file.c
1670 # etc..
1671 proc wokUtils:FILES:wtail { f n } {
1672     set ll [expr [llength [set lif [file split $f]]] -$n]
1673     return [join [lrange $lif $ll end] /]
1674 }
1675
1676 # Generate entry for one source file in Visual Studio 10 project file
1677 proc osutils:vcxproj:cxxfile { theFile theParams theSrcFileLevel } {
1678   if { $theParams == "" } {
1679     return "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile $theSrcFileLevel]]\" />\n"
1680   }
1681
1682   set aParams [string trim ${theParams}]
1683   append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
1684   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1685   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|Win32\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1686   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Debug|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1687   append text "      <AdditionalOptions Condition=\"\'\$(Configuration)|\$(Platform)\'==\'Release|x64\'\">${aParams} %(AdditionalOptions)</AdditionalOptions>\n"
1688   append text "    </ClCompile>\n"
1689   return $text
1690 }
1691
1692 # Generate entry for one header file in Visual Studio 10 project file
1693 proc osutils:vcxproj:hxxfile { theFile } { return "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\" />\n" }
1694
1695 # Generate Visual Studio 2010 project filters file
1696 proc osutils:vcxproj:filters { dir proj theCxxFilesMap theHxxFilesMap } {
1697   upvar $theCxxFilesMap aCxxFilesMap
1698   upvar $theHxxFilesMap aHxxFilesMap
1699
1700   # header
1701   append text "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
1702   append text "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
1703
1704   # list of "filters" (units)
1705   append text "  <ItemGroup>\n"
1706   append text "    <Filter Include=\"Source files\">\n"
1707   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1708   append text "    </Filter>\n"
1709   append text "    <Filter Include=\"Header files\">\n"
1710   append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1711   append text "    </Filter>\n"
1712   foreach unit $aCxxFilesMap(units) {
1713     append text "    <Filter Include=\"Source files\\${unit}\">\n"
1714     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1715     append text "    </Filter>\n"
1716   }
1717   foreach unit $aHxxFilesMap(units) {
1718     append text "    <Filter Include=\"Header files\\${unit}\">\n"
1719     append text "      <UniqueIdentifier>[OS:genGUID]</UniqueIdentifier>\n"
1720     append text "    </Filter>\n"
1721   }
1722   append text "  </ItemGroup>\n"
1723
1724   # list of cxx files
1725   append text "  <ItemGroup>\n"
1726   foreach unit $aCxxFilesMap(units) {
1727     foreach file $aCxxFilesMap($unit) {
1728       append text "    <ClCompile Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1729       append text "      <Filter>Source files\\${unit}</Filter>\n"
1730       append text "    </ClCompile>\n"
1731     }
1732   }
1733   append text "  </ItemGroup>\n"
1734
1735   # list of hxx files
1736   append text "  <ItemGroup>\n"
1737   foreach unit $aHxxFilesMap(units) {
1738     foreach file $aHxxFilesMap($unit) {
1739       append text "    <ClInclude Include=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $file 3]]\">\n"
1740       append text "      <Filter>Header files\\${unit}</Filter>\n"
1741       append text "    </ClInclude>\n"
1742     }
1743   }
1744   append text "  </ItemGroup>\n"
1745
1746   append text "  <ItemGroup>\n"
1747   append text "    <ResourceCompile Include=\"${proj}.rc\" />\n"
1748   append text "  </ItemGroup>\n"
1749
1750   # end
1751   append text "</Project>"
1752
1753   # write file
1754   set fp [open [set fvcproj [file join $dir ${proj}.vcxproj.filters]] w]
1755   fconfigure $fp -translation crlf
1756   puts $fp $text
1757   close $fp
1758
1759   return ${proj}.vcxproj.filters
1760 }
1761
1762 # Generate RC file content for ToolKit from template
1763 proc osutils:readtemplate:rc {theOutDir theToolKit} {
1764   set aLoc "$::THE_CASROOT/adm/templates/template_dll.rc"
1765   set aBody [wokUtils:FILES:FileToString $aLoc]
1766   regsub -all -- {__TKNAM__} $aBody $theToolKit aBody
1767
1768   set aFile [open "${theOutDir}/${theToolKit}.rc" "w"]
1769   fconfigure $aFile -translation lf
1770   puts $aFile $aBody
1771   close $aFile
1772   return "${theOutDir}/${theToolKit}.rc"
1773 }
1774
1775 # Generate Visual Studio project file for ToolKit
1776 proc osutils:vcproj { theVcVer isUWP theOutDir theToolKit theGuidsMap theSrcDir theSourceDirOther } {
1777   global path
1778
1779   set aHasQtDep "false"
1780   foreach aCsfElem [osutils:tk:csfInExternlib "$path/$theSrcDir/${theToolKit}/EXTERNLIB"] {
1781     if { "$aCsfElem" == "CSF_QT" } {
1782       set aHasQtDep "true"
1783     }
1784   }
1785   set theProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 0]
1786
1787   set l_compilable [osutils:compilable wnt]
1788   regsub -all -- {__TKNAM__} $theProjTmpl $theToolKit theProjTmpl
1789
1790   upvar $theGuidsMap aGuidsMap
1791   if { ! [info exists aGuidsMap($theToolKit)] } {
1792     set aGuidsMap($theToolKit) [OS:genGUID]
1793   }
1794   regsub -all -- {__PROJECT_GUID__} $theProjTmpl $aGuidsMap($theToolKit) theProjTmpl
1795
1796   set theProjTmpl [osutils:uwp:proj $isUWP ${theProjTmpl}]
1797
1798   set aUsedLibs [list]
1799
1800   if { $isUWP } {
1801     lappend aUsedLibs "WindowsApp.lib"
1802   }
1803
1804   foreach tkx [osutils:commonUsedTK  $theToolKit $theSrcDir $theSourceDirOther] {
1805     lappend aUsedLibs "${tkx}.lib"
1806   }
1807
1808   set anOsReleaseLibs {}
1809   set anOsDebugLibs {}
1810   osutils:usedOsLibs $theToolKit "wnt" anOsReleaseLibs aFrameworks $theSrcDir true
1811   osutils:usedOsLibs $theToolKit "wnt" anOsDebugLibs aFrameworks $theSrcDir false
1812
1813   # correct names of referred third-party libraries that are named with suffix
1814   # depending on VC version
1815   regsub -all -- {__TKDEP__} $theProjTmpl [osutils:depLibraries $aUsedLibs $anOsReleaseLibs $theVcVer] theProjTmpl
1816   regsub -all -- {__TKDEP_DEBUG__} $theProjTmpl [osutils:depLibraries $aUsedLibs $anOsDebugLibs $theVcVer] theProjTmpl
1817
1818   set anIncPaths "..\\..\\..\\inc"
1819 #  set aTKDefines ""
1820   set aFilesSection ""
1821   set aVcFilesCxx(units) ""
1822   set aVcFilesHxx(units) ""
1823   set listloc [osutils:tk:units $theToolKit $theSrcDir]
1824   if [array exists written] { unset written }
1825   #puts "\t1 [wokparam -v %CMPLRS_CXX_Options [w_info -f]] father"
1826   #puts "\t2 [wokparam -v %CMPLRS_CXX_Options] branch"
1827   #puts "\t1 [wokparam -v %CMPLRS_C_Options [w_info -f]] father"
1828   #puts "\t2 [wokparam -v %CMPLRS_C_Options] branch"
1829   set fxloparamfcxx [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx f] [_get_options wnt cmplrs_cxx b]] 2]
1830   set fxloparamfc   [lindex [osutils:intersect3 [_get_options wnt cmplrs_c f] [_get_options wnt cmplrs_c b]] 2]
1831   set fxloparam ""
1832   foreach fxlo $listloc {
1833     set xlo $fxlo
1834     set aSrcFiles [osutils:tk:cxxfiles $xlo wnt $theSrcDir]
1835     set aHxxFiles [osutils:tk:hxxfiles $xlo wnt $theSrcDir]
1836
1837     # prepare Qt moc files, appears only in Inspector - directory tools
1838     set aGeneratedFiles {}
1839     if { "$aHasQtDep" == "true" } {
1840       set aMocResFiles [osutils:tk:mocfiles $aHxxFiles $theOutDir]
1841       set aGeneratedFiles [osutils:tk:execfiles $aMocResFiles $theOutDir moc${::SYS_EXE_SUFFIX} moc cpp]
1842
1843       set aQrcResFiles [osutils:tk:qrcfiles $xlo wnt $theSrcDir]
1844       set aQrcFiles [osutils:tk:execfiles $aQrcResFiles $theOutDir rcc${::SYS_EXE_SUFFIX} rcc cpp]
1845       foreach resFile $aQrcFiles {
1846         lappend aGeneratedFiles $resFile
1847       }
1848     }
1849
1850     set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx $fxlo]
1851     if {$fxlo_cmplrs_options_cxx == ""} {
1852       set fxlo_cmplrs_options_cxx [_get_options wnt cmplrs_cxx b]
1853     }
1854         set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c $fxlo]
1855     if {$fxlo_cmplrs_options_c == ""} {
1856       set fxlo_cmplrs_options_c [_get_options wnt cmplrs_c b]
1857     }
1858     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_cxx b] $fxlo_cmplrs_options_cxx] 2]"
1859     set fxloparam "$fxloparam [lindex [osutils:intersect3 [_get_options wnt cmplrs_c b] $fxlo_cmplrs_options_c] 2]"
1860         #puts "\t3 [wokparam -v %CMPLRS_CXX_Options] branch CXX "
1861         #puts "\t4 [wokparam -v %CMPLRS_CXX_Options $fxlo] $fxlo  CXX"
1862         #puts "\t5 [wokparam -v %CMPLRS_C_Options] branch C"
1863         #puts "\t6 [wokparam -v %CMPLRS_C_Options   $fxlo] $fxlo  C"
1864     set needparam ""
1865     foreach partopt $fxloparam {
1866       if {[string first "-I" $partopt] == "0"} {
1867         # this is an additional includes search path
1868         continue
1869       }
1870       set needparam "$needparam $partopt"
1871     }
1872
1873     # Format of projects in vc10+ is different from vc7-9
1874     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1875       foreach aSrcFile [lsort $aSrcFiles] {
1876         if { ![info exists written([file tail $aSrcFile])] } {
1877           set written([file tail $aSrcFile]) 1
1878           append aFilesSection [osutils:vcxproj:cxxfile $aSrcFile $needparam 3]
1879         } else {
1880           puts "Warning : in vcproj more than one occurences for [file tail $aSrcFile]"
1881         }
1882         if { ! [info exists aVcFilesCxx($xlo)] } { lappend aVcFilesCxx(units) $xlo }
1883         lappend aVcFilesCxx($xlo) $aSrcFile
1884       }
1885       foreach aHxxFile [lsort $aHxxFiles] {
1886         if { ![info exists written([file tail $aHxxFile])] } {
1887           set written([file tail $aHxxFile]) 1
1888           append aFilesSection [osutils:vcxproj:hxxfile $aHxxFile]
1889         } else {
1890           puts "Warning : in vcproj more than one occurences for [file tail $aHxxFile]"
1891         }
1892         if { ! [info exists aVcFilesHxx($xlo)] } { lappend aVcFilesHxx(units) $xlo }
1893         lappend aVcFilesHxx($xlo) $aHxxFile
1894       }
1895       foreach aGenFile [lsort $aGeneratedFiles] {
1896         if { ![info exists written([file tail $aGenFile])] } {
1897           set written([file tail $aGenFile]) 1
1898           append aFilesSection [osutils:vcxproj:cxxfile $aGenFile $needparam 5]
1899         } else {
1900           puts "Warning : in vcproj more than one occurences for [file tail $aGenFile]"
1901         }
1902         if { ! [info exists aVcFilesCxx($xlo)] } { lappend aVcFilesCxx(units) $xlo }
1903         lappend aVcFilesCxx($xlo) $aGenFile
1904       }
1905     } else {
1906       append aFilesSection "\t\t\t<Filter\n"
1907       append aFilesSection "\t\t\t\tName=\"${xlo}\"\n"
1908       append aFilesSection "\t\t\t\t>\n"
1909       foreach aSrcFile [lsort $aSrcFiles] {
1910         if { ![info exists written([file tail $aSrcFile])] } {
1911           set written([file tail $aSrcFile]) 1
1912           append aFilesSection [osutils:vcproj:file $theVcVer $aSrcFile $needparam]
1913         } else {
1914           puts "Warning : in vcproj more than one occurences for [file tail $aSrcFile]"
1915         }
1916       }
1917       append aFilesSection "\t\t\t</Filter>\n"
1918     }
1919   }
1920
1921   regsub -all -- {__TKINC__}  $theProjTmpl $anIncPaths theProjTmpl
1922   regsub -all -- {__FILES__}  $theProjTmpl $aFilesSection theProjTmpl
1923
1924   # write file
1925   set aFile [open [set aVcFiles [file join $theOutDir ${theToolKit}.[osutils:vcproj:ext $theVcVer]]] w]
1926   fconfigure $aFile -translation crlf
1927   puts $aFile $theProjTmpl
1928   close $aFile
1929
1930   # write filters file for vc10+
1931   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1932     lappend aVcFiles [osutils:vcxproj:filters $theOutDir $theToolKit aVcFilesCxx aVcFilesHxx]
1933   }
1934
1935   # write resource file
1936   lappend aVcFiles [osutils:readtemplate:rc $theOutDir $theToolKit]
1937
1938   return $aVcFiles
1939 }
1940
1941 # Appends OS libraries into the list of used libraries.
1942 # Corrects list of referred third-party libraries that are named with suffix
1943 # depending on VC version
1944 # Unites list of used libraries into a variable with separator for VStudio older than vc9
1945 # @param theUsedLibs List of libraries, to be changed
1946 # @param theOsLibs List of Os library names, before using an extension should be added
1947 # @param theVcVer version of VStudio
1948
1949 proc osutils:depLibraries { theUsedLibs theOsLibs theVcVer } {
1950   foreach aLibIter $theOsLibs {
1951     lappend theUsedLibs "${aLibIter}.${::SYS_LIB_SUFFIX}"
1952   }
1953
1954   # correct names of referred third-party libraries that are named with suffix
1955   # depending on VC version
1956   set aVCRTVer [string range $theVcVer 0 3]
1957   regsub -all -- {vc[0-9]+} $theUsedLibs $aVCRTVer theUsedLibs
1958
1959   # and put this list to project file
1960   if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
1961     set theUsedLibs [join $theUsedLibs {;}]
1962   }
1963
1964   return $theUsedLibs
1965 }
1966
1967 # for a unit returns a map containing all its file in the current
1968 # workbench
1969 # local = 1 only local files
1970 proc osutils:tk:loadunit { loc map theSrcDir} {
1971   #puts $loc
1972   upvar $map TLOC
1973   catch { unset TLOC }
1974   set lfiles [_get_used_files $loc $theSrcDir]
1975   foreach f $lfiles {
1976     #puts "\t$f"
1977     set t [lindex $f 0]
1978     set p [lindex $f 2]
1979     if [info exists TLOC($t)] {
1980       set l $TLOC($t)
1981       lappend l $p
1982       set TLOC($t) $l
1983     } else {
1984       set TLOC($t) $p
1985     }
1986   }
1987   return
1988 }
1989
1990 # Returns the list of all files name in a toolkit within specified list of file extensions.
1991 proc osutils:tk:files { tkloc theExtensions theSrcDir } {
1992   set Tfiles(source,nocdlpack)     {source pubinclude}
1993   set Tfiles(source,toolkit)       {}
1994   set Tfiles(source,executable)    {source pubinclude}
1995   set listloc [concat [osutils:tk:units $tkloc $theSrcDir] $tkloc ]
1996   #puts " listloc = $listloc"
1997
1998   set resultloc $listloc
1999   set lret {}
2000   foreach loc $resultloc {
2001     set utyp [_get_type $loc]
2002     #puts "\"$utyp\" \"$loc\""
2003     switch $utyp {
2004          "t" { set utyp "toolkit" }
2005          "n" { set utyp "nocdlpack" }
2006          "x" { set utyp "executable" }
2007          default { error "Error: Cannot determine type of unit $loc, check adm/UDLIST!" }
2008     }
2009     if [array exists map] { unset map }
2010     osutils:tk:loadunit $loc map $theSrcDir
2011     #puts " loc = $loc === > [array names map]"
2012     set LType $Tfiles(source,${utyp})
2013     foreach typ [array names map] {
2014       if { [lsearch $LType $typ] == -1 } {
2015         unset map($typ)
2016       }
2017     }
2018     foreach type [array names map] {
2019       #puts $type
2020       foreach f $map($type) {
2021         #puts $f
2022         if { [lsearch $theExtensions [file extension $f]] != -1 } {
2023           lappend lret $f
2024         }
2025       }
2026     }
2027   }
2028   return $lret
2029 }
2030
2031 # Returns the list of all compilable files name in a toolkit.
2032 proc osutils:tk:cxxfiles { tkloc thePlatform theSrcDir } { return [osutils:tk:files $tkloc [osutils:compilable $thePlatform] $theSrcDir] }
2033
2034 # Returns the list of all header files name in a toolkit.
2035 proc osutils:tk:hxxfiles { tkloc thePlatform theSrcDir } { return [osutils:tk:files $tkloc [osutils:fileExtensionsHeaders $thePlatform] $theSrcDir] }
2036
2037 # Returns the list of all resource (qrc) files name in a toolkit.
2038 proc osutils:tk:qrcfiles { tkloc thePlatform theSourceDir } { return [osutils:tk:files $tkloc [osutils:fileExtensionsResources $thePlatform] $theSourceDir] }
2039
2040 # Returns the list of all header files name in a toolkit.
2041 proc osutils:tk:mocfiles { HxxFiles theOutDir } {
2042   set lret {}
2043   foreach file $HxxFiles {
2044     # processing only files where Q_OBJECT exists
2045     set fd [open "$file" rb]
2046     set FILES [split [read $fd] "\n"]
2047     close $fd
2048
2049     set isQObject [expr [regexp "Q_OBJECT" $FILES]]
2050     if { ! $isQObject } {
2051       continue;
2052     }
2053     lappend lret $file
2054   }
2055   return $lret
2056 }
2057
2058 # Returns the list of all header files name in a toolkit.
2059 proc osutils:tk:execfiles { theFiles theOutDir theCommand thePrefix theExtension} {
2060   set lret {}
2061   set anOutDir $theOutDir/$thePrefix
2062   file mkdir $anOutDir
2063
2064   foreach file $theFiles {
2065     set aResourceName [file tail $file]
2066     set anOutFile $anOutDir/${thePrefix}_[file rootname $aResourceName].$theExtension
2067
2068     exec $theCommand $file -o $anOutFile
2069     lappend lret $anOutFile
2070   }
2071   return $lret
2072 }
2073
2074 # Generate Visual Studio project file for executable
2075 proc osutils:vcprojx { theVcVer isUWP theOutDir theToolKit theGuidsMap theSrcDir theSourceDirOther } {
2076   set aVcFiles {}
2077   foreach f [osutils:tk:cxxfiles $theToolKit wnt $theSrcDir] {
2078     set aProjTmpl [osutils:vcproj:readtemplate $theVcVer $isUWP 1]
2079
2080     set aProjName [file rootname [file tail $f]]
2081     set l_compilable [osutils:compilable wnt]
2082     regsub -all -- {__XQTNAM__} $aProjTmpl $aProjName aProjTmpl
2083
2084     upvar $theGuidsMap aGuidsMap
2085     if { ! [info exists aGuidsMap($aProjName)] } {
2086       set aGuidsMap($aProjName) [OS:genGUID]
2087     }
2088     regsub -all -- {__PROJECT_GUID__} $aProjTmpl $aGuidsMap($aProjName) aProjTmpl
2089
2090     set aUsedLibs [list]
2091     foreach tkx [osutils:commonUsedTK  $theToolKit $theSrcDir $theSourceDirOther] {
2092       lappend aUsedLibs "${tkx}.lib"
2093     }
2094
2095     set anOsReleaseLibs {}
2096     set anOsDebugLibs {}
2097     osutils:usedOsLibs $theToolKit "wnt" anOsReleaseLibs aFrameworks $theSrcDir true
2098     osutils:usedOsLibs $theToolKit "wnt" anOsDebugLibs aFrameworks $theSrcDir false
2099
2100     set aVCRTVer [string range $theVcVer 0 3]
2101     regsub -all -- {__TKDEP__} $aProjTmpl [osutils:depLibraries $aUsedLibs $anOsReleaseLibs $theVcVer] aProjTmpl
2102     regsub -all -- {__TKDEP_DEBUG__} $aProjTmpl [osutils:depLibraries $aUsedLibs $anOsDebugLibs $theVcVer] aProjTmpl
2103
2104     set aFilesSection ""
2105     set aVcFilesCxx(units) ""
2106         set aVcFilesHxx(units) ""
2107
2108     if { ![info exists written([file tail $f])] } {
2109       set written([file tail $f]) 1
2110
2111       if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
2112         append aFilesSection [osutils:vcxproj:cxxfile $f "" 3]
2113         if { ! [info exists aVcFilesCxx($theToolKit)] } { lappend aVcFilesCxx(units) $theToolKit }
2114         lappend aVcFilesCxx($theToolKit) $f
2115       } else {
2116         append aFilesSection "\t\t\t<Filter\n"
2117         append aFilesSection "\t\t\t\tName=\"$theToolKit\"\n"
2118         append aFilesSection "\t\t\t\t>\n"
2119         append aFilesSection [osutils:vcproj:file $theVcVer $f ""]
2120         append aFilesSection "\t\t\t</Filter>"
2121       }
2122     } else {
2123       puts "Warning : in vcproj there are more than one occurences for [file tail $f]"
2124     }
2125     #puts "$aProjTmpl $aFilesSection"
2126     set anIncPaths "..\\..\\..\\inc"
2127     regsub -all -- {__TKINC__}  $aProjTmpl $anIncPaths    aProjTmpl
2128     regsub -all -- {__FILES__}  $aProjTmpl $aFilesSection aProjTmpl
2129     regsub -all -- {__CONF__}   $aProjTmpl Application    aProjTmpl
2130
2131     regsub -all -- {__XQTEXT__} $aProjTmpl "exe" aProjTmpl
2132
2133     set aFile [open [set aVcFilePath [file join $theOutDir ${aProjName}.[osutils:vcproj:ext $theVcVer]]] w]
2134     fconfigure $aFile -translation crlf
2135     puts $aFile $aProjTmpl
2136     close $aFile
2137
2138     set aCommonSettingsFile "$aVcFilePath.user"
2139     lappend aVcFiles $aVcFilePath
2140
2141     # write filters file for vc10
2142     if { "$theVcVer" != "vc7" && "$theVcVer" != "vc8" && "$theVcVer" != "vc9" } {
2143       lappend aVcFiles [osutils:vcxproj:filters $theOutDir $aProjName aVcFilesCxx aVcFilesHxx]
2144     }
2145
2146     # write resource file
2147     lappend aVcFiles [osutils:readtemplate:rc $theOutDir $aProjName]
2148
2149     set aCommonSettingsFileTmpl ""
2150     if { "$theVcVer" == "vc7" || "$theVcVer" == "vc8" } {
2151       # nothing
2152     } elseif { "$theVcVer" == "vc9" } {
2153       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcproj.user.vc9x"]
2154     } else {
2155       set aCommonSettingsFileTmpl [wokUtils:FILES:FileToString "$::THE_CASROOT/adm/templates/vcxproj.user.vc10x"]
2156     }
2157     if { "$aCommonSettingsFileTmpl" != "" } {
2158       regsub -all -- {__VCVER__} $aCommonSettingsFileTmpl $aVCRTVer aCommonSettingsFileTmpl
2159
2160       set aFile [open [set aVcFilePath "$aCommonSettingsFile"] w]
2161       fconfigure $aFile -translation crlf
2162       puts $aFile $aCommonSettingsFileTmpl
2163       close $aFile
2164
2165       lappend aVcFiles "$aCommonSettingsFile"
2166     }
2167   }
2168   return $aVcFiles
2169 }
2170
2171 # Generate entry for one source file in Visual Studio 7 - 9 project file
2172 proc osutils:vcproj:file { theVcVer theFile theOptions } {
2173   append aText "\t\t\t\t<File\n"
2174   append aText "\t\t\t\t\tRelativePath=\"..\\..\\..\\[wokUtils:EASY:bs1 [wokUtils:FILES:wtail $theFile 3]]\">\n"
2175   if { $theOptions == "" } {
2176     append aText "\t\t\t\t</File>\n"
2177     return $aText
2178   }
2179
2180   append aText "\t\t\t\t\t<FileConfiguration\n"
2181   append aText "\t\t\t\t\t\tName=\"Release\|Win32\">\n"
2182   append aText "\t\t\t\t\t\t<Tool\n"
2183   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2184   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2185   foreach aParam $theOptions {
2186     append aText "$aParam "
2187   }
2188   append aText "\"\n"
2189   append aText "\t\t\t\t\t\t/>\n"
2190   append aText "\t\t\t\t\t</FileConfiguration>\n"
2191
2192   append aText "\t\t\t\t\t<FileConfiguration\n"
2193   append aText "\t\t\t\t\t\tName=\"Debug\|Win32\">\n"
2194   append aText "\t\t\t\t\t\t<Tool\n"
2195   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2196   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2197   foreach aParam $theOptions {
2198     append aText "$aParam "
2199   }
2200   append aText "\"\n"
2201   append aText "\t\t\t\t\t\t/>\n"
2202   append aText "\t\t\t\t\t</FileConfiguration>\n"
2203   if { "$theVcVer" == "vc7" } {
2204     append aText "\t\t\t\t</File>\n"
2205     return $aText
2206   }
2207
2208   append aText "\t\t\t\t\t<FileConfiguration\n"
2209   append aText "\t\t\t\t\t\tName=\"Release\|x64\">\n"
2210   append aText "\t\t\t\t\t\t<Tool\n"
2211   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2212   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2213   foreach aParam $theOptions {
2214     append aText "$aParam "
2215   }
2216   append aText "\"\n"
2217   append aText "\t\t\t\t\t\t/>\n"
2218   append aText "\t\t\t\t\t</FileConfiguration>\n"
2219
2220   append aText "\t\t\t\t\t<FileConfiguration\n"
2221   append aText "\t\t\t\t\t\tName=\"Debug\|x64\">\n"
2222   append aText "\t\t\t\t\t\t<Tool\n"
2223   append aText "\t\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
2224   append aText "\t\t\t\t\t\t\tAdditionalOptions=\""
2225   foreach aParam $theOptions {
2226     append aText "$aParam "
2227   }
2228   append aText "\"\n"
2229   append aText "\t\t\t\t\t\t/>\n"
2230   append aText "\t\t\t\t\t</FileConfiguration>\n"
2231
2232   append aText "\t\t\t\t</File>\n"
2233   return $aText
2234 }
2235
2236 proc wokUtils:FILES:mkdir { d } {
2237     global tcl_version
2238     regsub -all {\.[^.]*} $tcl_version "" major
2239     if { $major == 8 } {
2240         file mkdir $d
2241     } else {
2242         if ![file exists $d] {
2243             if { "[info command mkdir]" == "mkdir" } {
2244                 mkdir -path $d
2245             } else {
2246                 puts stderr "wokUtils:FILES:mkdir : Error unable to find a mkdir command."
2247             }
2248         }
2249     }
2250     if [file exists $d] {
2251         return $d
2252     } else {
2253         return {}
2254     }
2255 }
2256
2257 # remove from listloc OpenCascade units indesirables on Unix
2258 proc osutils:justunix { listloc } {
2259   if { "$::tcl_platform(os)" == "Darwin" } {
2260     set goaway [list Xw WNT]
2261   } else {
2262     set goaway [list WNT]
2263   }
2264   return [osutils:juststation $goaway $listloc]
2265 }
2266
2267
2268 ####### CODEBLOCK ###################################################################
2269 # Function to generate Code Blocks workspace and project files
2270 proc OS:MKCBP { theOutDir theModules theAllSolution thePlatform theCmpl } {
2271   puts stderr "Generating project files for Code Blocks"
2272
2273   # Generate projects for toolkits and separate workspace for each module
2274   foreach aModule $theModules {
2275     OS:cworkspace          $aModule $aModule $theOutDir
2276     OS:cbp        $theCmpl $aModule          $theOutDir $thePlatform
2277   }
2278
2279   # Generate single workspace "OCCT" containing projects from all modules
2280   if { "$theAllSolution" != "" } {
2281     OS:cworkspace $theAllSolution $theModules $theOutDir
2282   }
2283
2284   puts "The Code Blocks workspace and project files are stored in the $theOutDir directory"
2285 }
2286
2287 # Generate Code Blocks projects
2288 proc OS:cbp { theCmpl theModules theOutDir thePlatform } {
2289   set aProjectFiles {}
2290   foreach aModule $theModules {
2291     foreach aToolKit [${aModule}:toolkits] {
2292       lappend aProjectFiles [osutils:cbptk $theCmpl $theOutDir $aToolKit $thePlatform]
2293     }
2294     foreach anExecutable [OS:executable ${aModule}] {
2295       lappend aProjectFiles [osutils:cbpx  $theCmpl $theOutDir $anExecutable $thePlatform]
2296     }
2297   }
2298   return $aProjectFiles
2299 }
2300
2301 # Generate Code::Blocks project file for ToolKit
2302 proc osutils:cbptk { theCmpl theOutDir theToolKit thePlatform} {
2303   set aUsedLibs     [list]
2304   set aFrameworks   [list]
2305   set anIncPaths    [list]
2306   set aTKDefines    [list]
2307   set aTKSrcFiles   [list]
2308
2309   # collect list of referred libraries to link with
2310   osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks "src"
2311   set aDepToolkits [wokUtils:LIST:Purge [osutils:tk:close $theToolKit "src" ""]]
2312   foreach tkx $aDepToolkits {
2313     lappend aUsedLibs "${tkx}"
2314   }
2315
2316   lappend anIncPaths "../../../inc"
2317   set listloc [osutils:tk:units $theToolKit "src"]
2318
2319   if { [llength $listloc] == 0 } {
2320     set listloc $theToolKit
2321   }
2322
2323   if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2324     set resultloc [osutils:justwnt  $listloc]
2325   } else {
2326     set resultloc [osutils:justunix $listloc]
2327   }
2328   if [array exists written] { unset written }
2329   foreach fxlo $resultloc {
2330     set xlo       $fxlo
2331     set aSrcFiles [osutils:tk:cxxfiles $xlo $thePlatform "src"]
2332     foreach aSrcFile [lsort $aSrcFiles] {
2333       if { ![info exists written([file tail $aSrcFile])] } {
2334         set written([file tail $aSrcFile]) 1
2335         lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2336       } else {
2337         puts "Warning : more than one occurences for [file tail $aSrcFile]"
2338       }
2339     }
2340
2341     # macros for correct DLL exports
2342 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2343 #      lappend aTKDefines "__${xlo}_DLL"
2344 #    }
2345   }
2346
2347   return [osutils:cbp $theCmpl $theOutDir $theToolKit $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines]
2348 }
2349
2350 # Generates Code Blocks workspace.
2351 proc OS:cworkspace { theSolName theModules theOutDir } {
2352   global path
2353   set aWsFilePath "${theOutDir}/${theSolName}.workspace"
2354   set aFile [open $aWsFilePath "w"]
2355   set isActiveSet 0
2356   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2357   puts $aFile "<CodeBlocks_workspace_file>"
2358   puts $aFile "\t<Workspace title=\"${theSolName}\">"
2359
2360   # collect list of projects to be created
2361   foreach aModule $theModules {
2362     # toolkits
2363     foreach aToolKit [osutils:tk:sort [${aModule}:toolkits] "src" ""] {
2364       set aDependencies [LibToLink $aToolKit "src" ""]
2365       if { [llength $aDependencies] == 0 } {
2366         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" />"
2367       } else {
2368         puts $aFile "\t\t<Project filename=\"${aToolKit}.cbp\" >"
2369         foreach aDepTk $aDependencies {
2370           puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2371         }
2372         puts $aFile "\t\t</Project>"
2373       }
2374     }
2375
2376     # executables, assume one project per cxx file...
2377     foreach aUnit [OS:executable ${aModule}] {
2378       set aUnitLoc $aUnit
2379       set src_files [_get_used_files $aUnit "src" false]
2380       set aSrcFiles {}
2381       foreach s $src_files { 
2382         regexp {source ([^\s]+)} $s dummy name
2383         lappend aSrcFiles $name
2384       }
2385       foreach aSrcFile $aSrcFiles {
2386         set aFileExtension [file extension $aSrcFile]
2387         if { $aFileExtension == ".cxx" } {
2388           set aPrjName [file rootname $aSrcFile]
2389           set aDependencies [list]
2390           if {[file isdirectory $path/src/$aUnitLoc]} {
2391             set aDependencies [LibToLinkX $aUnitLoc [file rootname $aSrcFile] "src" ""]
2392           }
2393           set anActiveState ""
2394           if { $isActiveSet == 0 } {
2395             set anActiveState " active=\"1\""
2396             set isActiveSet 1
2397           }
2398           if { [llength $aDependencies] == 0 } {
2399             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}/>"
2400           } else {
2401             puts $aFile "\t\t<Project filename=\"${aPrjName}.cbp\"${anActiveState}>"
2402             foreach aDepTk $aDependencies {
2403               puts $aFile "\t\t\t<Depends filename=\"${aDepTk}.cbp\" />"
2404             }
2405             puts $aFile "\t\t</Project>"
2406           }
2407         }
2408       }
2409     }
2410   }
2411
2412   puts $aFile "\t</Workspace>"
2413   puts $aFile "</CodeBlocks_workspace_file>"
2414   close $aFile
2415
2416   return $aWsFilePath
2417 }
2418
2419 # Generate Code::Blocks project file for Executable
2420 proc osutils:cbpx { theCmpl theOutDir theToolKit thePlatform } {
2421   global path
2422   set aWokArch    "$::env(ARCH)"
2423
2424   set aCbpFiles {}
2425   foreach aSrcFile [osutils:tk:cxxfiles $theToolKit $thePlatform "src"] {
2426     # collect list of referred libraries to link with
2427     set aUsedLibs     [list]
2428     set aFrameworks   [list]
2429     set anIncPaths    [list]
2430     set aTKDefines    [list]
2431     set aTKSrcFiles   [list]
2432     set aProjName [file rootname [file tail $aSrcFile]]
2433
2434     osutils:usedOsLibs $theToolKit $thePlatform aUsedLibs aFrameworks "src"
2435
2436     set aDepToolkits [LibToLinkX $theToolKit $aProjName "src" ""]
2437     foreach tkx $aDepToolkits {
2438       if {[_get_type $tkx] == "t"} {
2439         lappend aUsedLibs "${tkx}"
2440       }
2441       if {[lsearch [glob -tails -directory "$path/src" -types d *] $tkx] == "-1"} {
2442         lappend aUsedLibs "${tkx}"
2443       }
2444     }
2445
2446     set WOKSteps_exec_link [_get_options lin WOKSteps_exec_link $theToolKit]
2447     if { [regexp {WOKStep_DLLink} $WOKSteps_exec_link] || [regexp {WOKStep_Libink} $WOKSteps_exec_link] } {
2448       set isExecutable "false"
2449     } else {
2450       set isExecutable "true"
2451     }
2452
2453     if { ![info exists written([file tail $aSrcFile])] } {
2454       set written([file tail $aSrcFile]) 1
2455       lappend aTKSrcFiles "../../../[wokUtils:FILES:wtail $aSrcFile 3]"
2456     } else {
2457       puts "Warning : in cbp there are more than one occurences for [file tail $aSrcFile]"
2458     }
2459
2460     # macros for correct DLL exports
2461 #    if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
2462 #      lappend aTKDefines "__${theToolKit}_DLL"
2463 #    }
2464
2465     # common include paths
2466     lappend anIncPaths "../../../inc"
2467
2468     lappend aCbpFiles [osutils:cbp $theCmpl $theOutDir $aProjName $thePlatform $aTKSrcFiles $aUsedLibs $aFrameworks $anIncPaths $aTKDefines $isExecutable]
2469   }
2470
2471   return $aCbpFiles
2472 }
2473
2474 # This function intended to generate Code::Blocks project file
2475 # @param theCmpl       - the compiler (gcc or msvc)
2476 # @param theOutDir     - output directory to place project file
2477 # @param theProjName   - project name
2478 # @param theSrcFiles   - list of source files
2479 # @param theLibsList   - dependencies (libraries  list)
2480 # @param theFrameworks - dependencies (frameworks list, Mac OS X specific)
2481 # @param theIncPaths   - header search paths
2482 # @param theDefines    - compiler macro definitions
2483 # @param theIsExe      - flag to indicate executable / library target
2484 proc osutils:cbp { theCmpl theOutDir theProjName thePlatform theSrcFiles theLibsList theFrameworks theIncPaths theDefines {theIsExe "false"} } {
2485   set aWokArch    "$::env(ARCH)"
2486
2487   set aCmplCbp "gcc"
2488   set aCmplFlags        [list]
2489   set aCmplFlagsRelease [list]
2490   set aCmplFlagsDebug   [list]
2491   set toPassArgsByFile 0
2492   set aLibPrefix "lib"
2493   set aPlatformAndCompiler "${thePlatform}/gcc"
2494   if { "$thePlatform" == "mac" || "$thePlatform" == "ios" } {
2495     set aPlatformAndCompiler "${thePlatform}/clang"
2496   }
2497   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" || "$thePlatform" == "qnx" } {
2498     set toPassArgsByFile 1
2499   }
2500   if { "$theCmpl" == "msvc" } {
2501     set aCmplCbp "msvc8"
2502     set aLibPrefix ""
2503   }
2504
2505   if { "$theCmpl" == "msvc" } {
2506     set aCmplFlags        "-arch:SSE2 -EHsc -W4 -MP"
2507     set aCmplFlagsRelease "-MD  -O2"
2508     set aCmplFlagsDebug   "-MDd -Od -Zi"
2509     lappend aCmplFlags    "-D_CRT_SECURE_NO_WARNINGS"
2510     lappend aCmplFlags    "-D_CRT_NONSTDC_NO_DEPRECATE"
2511   } elseif { "$theCmpl" == "gcc" } {
2512     if { "$thePlatform" != "qnx" } {
2513       set aCmplFlags      "-mmmx -msse -msse2 -mfpmath=sse"
2514     }
2515     set aCmplFlagsRelease "-O2"
2516     set aCmplFlagsDebug   "-O0 -g"
2517     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2518       lappend aCmplFlags "-std=gnu++0x"
2519       lappend aCmplFlags "-D_WIN32_WINNT=0x0501"
2520     } else {
2521       lappend aCmplFlags "-std=c++0x"
2522       lappend aCmplFlags "-fPIC"
2523       lappend aCmplFlags "-DOCC_CONVERT_SIGNALS"
2524     }
2525     lappend aCmplFlags   "-Wall"
2526     lappend aCmplFlags   "-fexceptions"
2527   }
2528   lappend aCmplFlagsRelease "-DNDEBUG"
2529   lappend aCmplFlagsRelease "-DNo_Exception"
2530   lappend aCmplFlagsDebug   "-D_DEBUG"
2531   if { "$thePlatform" == "qnx" } {
2532     lappend aCmplFlags "-D_QNX_SOURCE"
2533   }
2534
2535   set aCbpFilePath    "${theOutDir}/${theProjName}.cbp"
2536   set aLnkFileName    "${theProjName}_obj.link"
2537   set aLnkDebFileName "${theProjName}_objd.link"
2538   set aLnkFilePath    "${theOutDir}/${aLnkFileName}"
2539   set aLnkDebFilePath "${theOutDir}/${aLnkDebFileName}"
2540   set aFile [open $aCbpFilePath "w"]
2541   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"
2542   puts $aFile "<CodeBlocks_project_file>"
2543   puts $aFile "\t<FileVersion major=\"1\" minor=\"6\" />"
2544   puts $aFile "\t<Project>"
2545   puts $aFile "\t\t<Option title=\"$theProjName\" />"
2546   puts $aFile "\t\t<Option pch_mode=\"2\" />"
2547   puts $aFile "\t\t<Option compiler=\"$aCmplCbp\" />"
2548   puts $aFile "\t\t<Build>"
2549
2550   # Release target configuration
2551   puts $aFile "\t\t\t<Target title=\"Release\">"
2552   if { "$theIsExe" == "true" } {
2553     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bin/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2554     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2555   } else {
2556     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2557       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\" />"
2558     } else {
2559       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/lib/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2560     }
2561     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2562   }
2563   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/obj\" />"
2564   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2565   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2566   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2567     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2568   } else {
2569     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2570   }
2571
2572   # compiler options per TARGET (including defines)
2573   puts $aFile "\t\t\t\t<Compiler>"
2574   foreach aFlagIter $aCmplFlagsRelease {
2575     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2576   }
2577   foreach aMacro $theDefines {
2578     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2579   }
2580   puts $aFile "\t\t\t\t</Compiler>"
2581
2582   puts $aFile "\t\t\t\t<Linker>"
2583   if { $toPassArgsByFile == 1 } {
2584     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkFileName\" />"
2585   }
2586   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/lib\" />"
2587   if { "$thePlatform" == "mac" } {
2588     if { [ lsearch $theLibsList X11 ] >= 0} {
2589       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2590     }
2591   }
2592   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch})\" />"
2593   if { "$thePlatform" == "lin" } {
2594     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/lib\" />"
2595   }
2596   puts $aFile "\t\t\t\t</Linker>"
2597
2598   puts $aFile "\t\t\t</Target>"
2599
2600   # Debug target configuration
2601   puts $aFile "\t\t\t<Target title=\"Debug\">"
2602   if { "$theIsExe" == "true" } {
2603     puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/bind/${theProjName}\" prefix_auto=\"0\" extension_auto=\"0\" />"
2604     puts $aFile "\t\t\t\t<Option type=\"1\" />"
2605   } else {
2606     if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2607       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\" />"
2608     } else {
2609       puts $aFile "\t\t\t\t<Option output=\"../../../${aPlatformAndCompiler}/libd/lib${theProjName}.so\" prefix_auto=\"0\" extension_auto=\"0\" />"
2610     }
2611     puts $aFile "\t\t\t\t<Option type=\"3\" />"
2612   }
2613   puts $aFile "\t\t\t\t<Option object_output=\"../../../${aPlatformAndCompiler}/objd\" />"
2614   puts $aFile "\t\t\t\t<Option compiler=\"$aCmplCbp\" />"
2615   puts $aFile "\t\t\t\t<Option createDefFile=\"0\" />"
2616   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2617     puts $aFile "\t\t\t\t<Option createStaticLib=\"1\" />"
2618   } else {
2619     puts $aFile "\t\t\t\t<Option createStaticLib=\"0\" />"
2620   }
2621
2622   # compiler options per TARGET (including defines)
2623   puts $aFile "\t\t\t\t<Compiler>"
2624   foreach aFlagIter $aCmplFlagsDebug {
2625     puts $aFile "\t\t\t\t\t<Add option=\"$aFlagIter\" />"
2626   }
2627   foreach aMacro $theDefines {
2628     puts $aFile "\t\t\t\t\t<Add option=\"-D${aMacro}\" />"
2629   }
2630   puts $aFile "\t\t\t\t</Compiler>"
2631
2632   puts $aFile "\t\t\t\t<Linker>"
2633   if { $toPassArgsByFile == 1 } {
2634     puts $aFile "\t\t\t\t\t<Add option=\"\@$aLnkDebFileName\" />"
2635   }
2636   puts $aFile "\t\t\t\t\t<Add directory=\"../../../${aPlatformAndCompiler}/libd\" />"
2637   if { "$thePlatform" == "mac" } {
2638     if { [ lsearch $theLibsList X11 ] >= 0} {
2639       puts $aFile "\t\t\t\t\t<Add directory=\"/usr/X11/lib\" />"
2640     }
2641   }
2642   puts $aFile "\t\t\t\t\t<Add option=\"\$(CSF_OPT_LNK${aWokArch}D)\" />"
2643   if { "$thePlatform" == "lin" } {
2644     puts $aFile "\t\t\t\t\t<Add option=\"-Wl,-rpath-link=../../../${aPlatformAndCompiler}/libd\" />"
2645   }
2646   puts $aFile "\t\t\t\t</Linker>"
2647
2648   puts $aFile "\t\t\t</Target>"
2649
2650   puts $aFile "\t\t</Build>"
2651
2652   # COMMON compiler options
2653   puts $aFile "\t\t<Compiler>"
2654   foreach aFlagIter $aCmplFlags {
2655     puts $aFile "\t\t\t<Add option=\"$aFlagIter\" />"
2656   }
2657   puts $aFile "\t\t\t<Add option=\"\$(CSF_OPT_CMPL)\" />"
2658   foreach anIncPath $theIncPaths {
2659     puts $aFile "\t\t\t<Add directory=\"$anIncPath\" />"
2660   }
2661   puts $aFile "\t\t</Compiler>"
2662
2663   # COMMON linker options
2664   puts $aFile "\t\t<Linker>"
2665   if { "$thePlatform" == "wnt" && "$theCmpl" == "gcc" } {
2666     puts $aFile "\t\t\t<Add option=\"-Wl,--export-all-symbols\" />"
2667   }
2668   foreach aFrameworkName $theFrameworks {
2669     if { "$aFrameworkName" != "" } {
2670       puts $aFile "\t\t\t<Add option=\"-framework $aFrameworkName\" />"
2671     }
2672   }
2673   foreach aLibName $theLibsList {
2674     if { "$aLibName" != "" } {
2675       if { "$theCmpl" == "msvc" } {
2676         puts $aFile "\t\t\t<Add library=\"${aLibName}.lib\" />"
2677       } else {
2678         puts $aFile "\t\t\t<Add library=\"${aLibName}\" />"
2679       }
2680     }
2681   }
2682   puts $aFile "\t\t</Linker>"
2683
2684   # list of sources
2685
2686   set aFileLnkObj ""
2687   set aFileLnkObjd ""
2688   set isFirstSrcFile 1
2689   if { $toPassArgsByFile == 1 } {
2690     set aFileLnkObj  [open $aLnkFilePath    "w"]
2691     set aFileLnkObjd [open $aLnkDebFilePath "w"]
2692   }
2693
2694   foreach aSrcFile $theSrcFiles {
2695     if {[string equal -nocase [file extension $aSrcFile] ".mm"]} {
2696       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2697       puts $aFile "\t\t\t<Option compile=\"1\" />"
2698       puts $aFile "\t\t\t<Option link=\"1\" />"
2699       puts $aFile "\t\t</Unit>"
2700     } elseif {[string equal -nocase [file extension $aSrcFile] ".c"]} {
2701       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2702       puts $aFile "\t\t\t<Option compilerVar=\"CC\" />"
2703       puts $aFile "\t\t</Unit>"
2704     } elseif { $toPassArgsByFile == 1 && $isFirstSrcFile == 0 && [string equal -nocase [file extension $aSrcFile] ".cxx" ] } {
2705       # pass at list single source file to Code::Blocks as is
2706       # and pack the list of other files into the dedicated file to workaround process arguments limits on systems like Windows
2707       puts $aFile "\t\t<Unit filename=\"$aSrcFile\">"
2708       puts $aFile "\t\t\t<Option link=\"0\" />"
2709       puts $aFile "\t\t</Unit>"
2710
2711       set aFileObj  [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/obj/src/"]  $aSrcFile]]
2712       set aFileObjd [string map {.cxx .o} [string map [list "/src/" "/${aPlatformAndCompiler}/objd/src/"] $aSrcFile]]
2713       puts -nonewline $aFileLnkObj  "$aFileObj "
2714       puts -nonewline $aFileLnkObjd "$aFileObjd "
2715     } else {
2716       puts $aFile "\t\t<Unit filename=\"$aSrcFile\" />"
2717       set isFirstSrcFile 0
2718     }
2719   }
2720
2721   if { "$thePlatform" == "wnt" || "$thePlatform" == "uwp" } {
2722     close $aFileLnkObj
2723     close $aFileLnkObjd
2724   }
2725
2726   puts $aFile "\t</Project>"
2727   puts $aFile "</CodeBlocks_project_file>"
2728   close $aFile
2729
2730   return $aCbpFilePath
2731 }
2732
2733 # Define libraries to link using only EXTERNLIB file
2734 proc LibToLinkX {thePackage theDummyName theSrcDir theSourceDirOther} {
2735   set aToolKits [LibToLink $thePackage $theSrcDir $theSourceDirOther]
2736   return $aToolKits
2737 }
2738
2739 # Function to generate Xcode workspace and project files
2740 proc OS:MKXCD { theOutDir {theModules {}} {theAllSolution ""} {theLibType "dynamic"} {thePlatform ""} } {
2741
2742   puts stderr "Generating project files for Xcode"
2743
2744   # Generate projects for toolkits and separate workspace for each module
2745   foreach aModule $theModules {
2746     OS:xcworkspace $aModule $aModule $theOutDir
2747     OS:xcodeproj   $aModule          $theOutDir ::THE_GUIDS_LIST $theLibType $thePlatform
2748   }
2749
2750   # Generate single workspace "OCCT" containing projects from all modules
2751   if { "$theAllSolution" != "" } {
2752     OS:xcworkspace $theAllSolution $theModules $theOutDir
2753   }
2754 }
2755
2756 # Generates toolkits sections for Xcode workspace file.
2757 proc OS:xcworkspace:toolkits { theModule } {
2758   set aBuff ""
2759
2760   # Adding toolkits for module in workspace.
2761   foreach aToolKit [osutils:tk:sort [${theModule}:toolkits] "src" ""] {
2762     append aBuff "         <FileRef\n"
2763     append aBuff "            location = \"group:${aToolKit}.xcodeproj\">\n"
2764     append aBuff "         </FileRef>\n"
2765   }
2766
2767   # Adding executables for module, assume one project per cxx file...
2768   foreach aUnit [OS:executable ${theModule}] {
2769     set aUnitLoc $aUnit
2770     set src_files [_get_used_files $aUnit "src" false]
2771     set aSrcFiles {}
2772     foreach s $src_files {
2773       regexp {source ([^\s]+)} $s dummy name
2774       lappend aSrcFiles $name
2775     }
2776     foreach aSrcFile $aSrcFiles {
2777       set aFileExtension [file extension $aSrcFile]
2778       if { $aFileExtension == ".cxx" } {
2779         set aPrjName [file rootname $aSrcFile]
2780         append aBuff "         <FileRef\n"
2781         append aBuff "            location = \"group:${aPrjName}.xcodeproj\">\n"
2782         append aBuff "         </FileRef>\n"
2783       }
2784     }
2785   }
2786
2787   # Removing unnecessary newline character from the end.
2788   set aBuff [string replace $aBuff end end]
2789   return $aBuff
2790 }
2791
2792 # Generates workspace files for Xcode.
2793 proc OS:xcworkspace { theWorkspaceName theModules theOutDir } {
2794   # Creating workspace directory for Xcode.
2795   set aWorkspaceDir "${theOutDir}/${theWorkspaceName}.xcworkspace"
2796   wokUtils:FILES:mkdir $aWorkspaceDir
2797   if { ! [file exists $aWorkspaceDir] } {
2798     puts stderr "Error: Could not create workspace directory \"$aWorkspaceDir\""
2799     return
2800   }
2801
2802   # Creating workspace file.
2803   set aWsFilePath "${aWorkspaceDir}/contents.xcworkspacedata"
2804   set aFile [open $aWsFilePath "w"]
2805
2806   # Adding header and section for main Group.
2807   puts $aFile "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
2808   puts $aFile "<Workspace"
2809   puts $aFile "   version = \"1.0\">"
2810   puts $aFile "   <Group"
2811   puts $aFile "      location = \"container:\""
2812   puts $aFile "      name = \"${theWorkspaceName}\">"
2813
2814   # Adding modules.
2815   if { [llength "$theModules"] > 1 } {
2816     foreach aModule $theModules {
2817       puts $aFile "      <Group"
2818       puts $aFile "         location = \"container:\""
2819       puts $aFile "         name = \"${aModule}\">"
2820       puts $aFile [OS:xcworkspace:toolkits $aModule]
2821       puts $aFile "      </Group>"
2822     }
2823   } else {
2824     puts $aFile [OS:xcworkspace:toolkits $theModules]
2825   }
2826
2827   # Adding footer.
2828   puts $aFile "   </Group>"
2829   puts $aFile "</Workspace>"
2830   close $aFile
2831 }
2832
2833 # Generates Xcode project files.
2834 proc OS:xcodeproj { theModules theOutDir theGuidsMap theLibType thePlatform} {
2835   upvar $theGuidsMap aGuidsMap
2836
2837   set isStatic 0
2838   if { "$theLibType" == "static" } {
2839     set isStatic 1
2840   } elseif { "$thePlatform" == "ios" } {
2841     set isStatic 1
2842   }
2843
2844   set aProjectFiles {}
2845   foreach aModule $theModules {
2846     foreach aToolKit [${aModule}:toolkits] {
2847       lappend aProjectFiles [osutils:xcdtk $theOutDir $aToolKit     aGuidsMap $isStatic $thePlatform "dylib"]
2848     }
2849     foreach anExecutable [OS:executable ${aModule}] {
2850       lappend aProjectFiles [osutils:xcdtk $theOutDir $anExecutable aGuidsMap $isStatic $thePlatform "executable"]
2851     }
2852   }
2853   return $aProjectFiles
2854 }
2855
2856 # Generates dependencies section for Xcode project files.
2857 proc osutils:xcdtk:deps {theToolKit theTargetType theGuidsMap theFileRefSection theDepsGuids theDepsRefGuids thePlatform theIsStatic} {
2858   upvar $theGuidsMap         aGuidsMap
2859   upvar $theFileRefSection   aFileRefSection
2860   upvar $theDepsGuids        aDepsGuids
2861   upvar $theDepsRefGuids     aDepsRefGuids
2862
2863   set aBuildFileSection ""
2864   set aUsedLibs         [wokUtils:LIST:Purge [osutils:tk:close $theToolKit "src" ""]]
2865   set aDepToolkits      [lappend [wokUtils:LIST:Purge [osutils:tk:close $theToolKit "src" ""]] $theToolKit]
2866
2867   if { "$theTargetType" == "executable" } {
2868     set aFile [osutils:tk:cxxfiles $theToolKit mac "src"]
2869     set aProjName [file rootname [file tail $aFile]]
2870     set aDepToolkits [LibToLinkX $theToolKit $aProjName "src" ""]
2871   }
2872
2873   set aLibExt "dylib"
2874   if { $theIsStatic == 1 } {
2875     set aLibExt "a"
2876     if { "$theTargetType" != "executable" } {
2877       return $aBuildFileSection
2878     }
2879   }
2880
2881   osutils:usedOsLibs $theToolKit $thePlatform aLibs aFrameworks "src"
2882   set aUsedLibs [concat $aUsedLibs $aLibs]
2883   set aUsedLibs [concat $aUsedLibs $aFrameworks]
2884   foreach tkx $aUsedLibs {
2885     set aDepLib    "${tkx}_Dep"
2886     set aDepLibRef "${tkx}_DepRef"
2887
2888     if { ! [info exists aGuidsMap($aDepLib)] } {
2889       set aGuidsMap($aDepLib) [OS:genGUID "xcd"]
2890     }
2891     if { ! [info exists aGuidsMap($aDepLibRef)] } {
2892       set aGuidsMap($aDepLibRef) [OS:genGUID "xcd"]
2893     }
2894
2895     append aBuildFileSection "\t\t$aGuidsMap($aDepLib) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aDepLibRef) ; \};\n"
2896     if {[lsearch -nocase $aFrameworks $tkx] == -1} {
2897       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = file; name = lib${tkx}.${aLibExt}; path = lib${tkx}.${aLibExt}; sourceTree = \"<group>\"; \};\n"
2898     } else {
2899       append aFileRefSection   "\t\t$aGuidsMap($aDepLibRef) = \{isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ${tkx}.framework; path = /System/Library/Frameworks/${tkx}.framework; sourceTree = \"<absolute>\"; \};\n"
2900     }
2901     append aDepsGuids        "\t\t\t\t$aGuidsMap($aDepLib) ,\n"
2902     append aDepsRefGuids     "\t\t\t\t$aGuidsMap($aDepLibRef) ,\n"
2903   }
2904
2905   return $aBuildFileSection
2906 }
2907
2908 # Generates PBXBuildFile and PBXGroup sections for project file.
2909 proc osutils:xcdtk:sources {theToolKit theTargetType theSrcFileRefSection theGroupSection thePackageGuids theSrcFileGuids theGuidsMap theIncPaths} {
2910   upvar $theSrcFileRefSection aSrcFileRefSection
2911   upvar $theGroupSection      aGroupSection
2912   upvar $thePackageGuids      aPackagesGuids
2913   upvar $theSrcFileGuids      aSrcFileGuids
2914   upvar $theGuidsMap          aGuidsMap
2915   upvar $theIncPaths          anIncPaths
2916
2917   set listloc [osutils:tk:units $theToolKit "src"]
2918   set resultloc [osutils:justunix $listloc]
2919   set aBuildFileSection ""
2920   set aPackages [lsort -nocase $resultloc]
2921   if { "$theTargetType" == "executable" } {
2922     set aPackages [list "$theToolKit"]
2923   }
2924
2925   # Generating PBXBuildFile, PBXGroup sections and groups for each package.
2926   foreach fxlo $aPackages {
2927     set xlo       $fxlo
2928     set aPackage "${xlo}_Package"
2929     set aSrcFileRefGuids ""
2930     if { ! [info exists aGuidsMap($aPackage)] } {
2931       set aGuidsMap($aPackage) [OS:genGUID "xcd"]
2932     }
2933
2934     set aSrcFiles [osutils:tk:cxxfiles $xlo mac "src"]
2935     foreach aSrcFile [lsort $aSrcFiles] {
2936       set aFileExt "sourcecode.cpp.cpp"
2937
2938       if { [file extension $aSrcFile] == ".c" } {
2939         set aFileExt "sourcecode.c.c"
2940       } elseif { [file extension $aSrcFile] == ".mm" } {
2941         set aFileExt "sourcecode.cpp.objcpp"
2942       }
2943
2944       if { ! [info exists aGuidsMap($aSrcFile)] } {
2945         set aGuidsMap($aSrcFile) [OS:genGUID "xcd"]
2946       }
2947       set aSrcFileRef "${aSrcFile}_Ref"
2948       if { ! [info exists aGuidsMap($aSrcFileRef)] } {
2949         set aGuidsMap($aSrcFileRef) [OS:genGUID "xcd"]
2950       }
2951       if { ! [info exists written([file tail $aSrcFile])] } {
2952         set written([file tail $aSrcFile]) 1
2953         append aBuildFileSection  "\t\t$aGuidsMap($aSrcFile) = \{isa = PBXBuildFile; fileRef = $aGuidsMap($aSrcFileRef) ;\};\n"
2954         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"
2955         append aSrcFileGuids      "\t\t\t\t$aGuidsMap($aSrcFile) ,\n"
2956         append aSrcFileRefGuids   "\t\t\t\t$aGuidsMap($aSrcFileRef) ,\n"
2957       } else {
2958         puts "Warning : more than one occurences for [file tail $aSrcFile]"
2959       }
2960     }
2961
2962     append aGroupSection "\t\t$aGuidsMap($aPackage) = \{\n"
2963     append aGroupSection "\t\t\tisa = PBXGroup;\n"
2964     append aGroupSection "\t\t\tchildren = (\n"
2965     append aGroupSection $aSrcFileRefGuids
2966     append aGroupSection "\t\t\t);\n"
2967     append aGroupSection "\t\t\tname = $xlo;\n"
2968     append aGroupSection "\t\t\tsourceTree = \"<group>\";\n"
2969     append aGroupSection "\t\t\};\n"
2970
2971     # Storing packages IDs for adding them later as a child of toolkit
2972     append aPackagesGuids "\t\t\t\t$aGuidsMap($aPackage) ,\n"
2973   }
2974
2975   # Removing unnecessary newline character from the end.
2976   set aPackagesGuids [string replace $aPackagesGuids end end]
2977
2978   return $aBuildFileSection
2979 }
2980
2981 # Creates folders structure and all necessary files for Xcode project.
2982 proc osutils:xcdtk { theOutDir theToolKit theGuidsMap theIsStatic thePlatform {theTargetType "dylib"} } {
2983   set aPBXBuildPhase "Headers"
2984   set aRunOnlyForDeployment "0"
2985   set aProductType "library.dynamic"
2986   set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = dylib;"
2987   set anExecPrefix "\t\t\t\tEXECUTABLE_PREFIX = lib;"
2988   set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = dylib;"
2989   set aTKDefines [list "OCC_CONVERT_SIGNALS"]
2990   if { $theIsStatic == 1 } {
2991     lappend aTKDefines "OCCT_NO_PLUGINS"
2992   }
2993
2994   if { "$theTargetType" == "executable" } {
2995     set aPBXBuildPhase "CopyFiles"
2996     set aRunOnlyForDeployment "1"
2997     set aProductType "tool"
2998     set anExecExtension ""
2999     set anExecPrefix ""
3000     set aWrapperExtension ""
3001   } elseif { $theIsStatic == 1 } {
3002     set aProductType "library.static"
3003     set anExecExtension "\t\t\t\tEXECUTABLE_EXTENSION = a;"
3004     set aWrapperExtension "\t\t\t\tWRAPPER_EXTENSION = a;"
3005   }
3006
3007   set aUsername [exec whoami]
3008
3009   # Creation of folders for Xcode projectP.
3010   set aToolkitDir "${theOutDir}/${theToolKit}.xcodeproj"
3011   wokUtils:FILES:mkdir $aToolkitDir
3012   if { ! [file exists $aToolkitDir] } {
3013     puts stderr "Error: Could not create project directory \"$aToolkitDir\""
3014     return
3015   }
3016
3017   set aUserDataDir "${aToolkitDir}/xcuserdata"
3018   wokUtils:FILES:mkdir $aUserDataDir
3019   if { ! [file exists $aUserDataDir] } {
3020     puts stderr "Error: Could not create xcuserdata directorty in \"$aToolkitDir\""
3021     return
3022   }
3023
3024   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
3025   wokUtils:FILES:mkdir $aUserDataDir
3026   if { ! [file exists $aUserDataDir] } {
3027     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directorty in \"$aToolkitDir\"/xcuserdata"
3028     return
3029   }
3030
3031   set aSchemesDir "${aUserDataDir}/xcschemes"
3032   wokUtils:FILES:mkdir $aSchemesDir
3033   if { ! [file exists $aSchemesDir] } {
3034     puts stderr "Error: Could not create xcschemes directorty in \"$aUserDataDir\""
3035     return
3036   }
3037   # End of folders creation.
3038
3039   # Generating GUID for tookit.
3040   upvar $theGuidsMap aGuidsMap
3041   if { ! [info exists aGuidsMap($theToolKit)] } {
3042     set aGuidsMap($theToolKit) [OS:genGUID "xcd"]
3043   }
3044
3045   # Creating xcscheme file for toolkit from template.
3046   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcd"]
3047   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theToolKit aXcschemeTmpl
3048   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theToolKit) aXcschemeTmpl
3049   set aXcschemeFile [open "$aSchemesDir/${theToolKit}.xcscheme"  "w"]
3050   puts $aXcschemeFile $aXcschemeTmpl
3051   close $aXcschemeFile
3052
3053   # Creating xcschememanagement.plist file for toolkit from template.
3054   set aPlistTmpl [osutils:readtemplate "plist" "xcd"]
3055   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theToolKit aPlistTmpl
3056   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theToolKit) aPlistTmpl
3057   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
3058   puts $aPlistFile $aPlistTmpl
3059   close $aPlistFile
3060
3061   # Creating project.pbxproj file for toolkit.
3062   set aPbxprojFile [open "$aToolkitDir/project.pbxproj" "w"]
3063   puts $aPbxprojFile "// !\$*UTF8*\$!"
3064   puts $aPbxprojFile "\{"
3065   puts $aPbxprojFile "\tarchiveVersion = 1;"
3066   puts $aPbxprojFile "\tclasses = \{"
3067   puts $aPbxprojFile "\t\};"
3068   puts $aPbxprojFile "\tobjectVersion = 46;"
3069   puts $aPbxprojFile "\tobjects = \{\n"
3070
3071   # Begin PBXBuildFile section
3072   set aPackagesGuids ""
3073   set aGroupSection ""
3074   set aSrcFileRefSection ""
3075   set aSrcFileGuids ""
3076   set aDepsFileRefSection ""
3077   set aDepsGuids ""
3078   set aDepsRefGuids ""
3079   set anIncPaths [list "../../../inc"]
3080   set anLibPaths ""
3081
3082   if { [info exists ::env(CSF_OPT_INC)] } {
3083     set anIncCfg [split "$::env(CSF_OPT_INC)" ":"]
3084     foreach anIncCfgPath $anIncCfg {
3085       lappend anIncPaths $anIncCfgPath
3086     }
3087   }
3088   if { [info exists ::env(CSF_OPT_LIB64)] } {
3089     set anLibCfg [split "$::env(CSF_OPT_LIB64)" ":"]
3090     foreach anLibCfgPath $anLibCfg {
3091       lappend anLibPaths $anLibCfgPath
3092     }
3093   }
3094
3095   puts $aPbxprojFile [osutils:xcdtk:sources $theToolKit $theTargetType aSrcFileRefSection aGroupSection aPackagesGuids aSrcFileGuids aGuidsMap anIncPaths]
3096   puts $aPbxprojFile [osutils:xcdtk:deps    $theToolKit $theTargetType aGuidsMap aDepsFileRefSection aDepsGuids aDepsRefGuids $thePlatform $theIsStatic]
3097   # End PBXBuildFile section
3098
3099   # Begin PBXFileReference section
3100   set aToolkitLib "lib${theToolKit}.dylib"
3101   set aPath "$aToolkitLib"
3102   if { "$theTargetType" == "executable" } {
3103     set aPath "$theToolKit"
3104   } elseif { $theIsStatic == 1 } {
3105     set aToolkitLib "lib${theToolKit}.a"
3106   }
3107
3108   if { ! [info exists aGuidsMap($aToolkitLib)] } {
3109     set aGuidsMap($aToolkitLib) [OS:genGUID "xcd"]
3110   }
3111
3112   puts $aPbxprojFile "\t\t$aGuidsMap($aToolkitLib) = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.${theTargetType}\"; includeInIndex = 0; path = $aPath; sourceTree = BUILT_PRODUCTS_DIR; };\n"
3113   puts $aPbxprojFile $aSrcFileRefSection
3114   puts $aPbxprojFile $aDepsFileRefSection
3115   # End PBXFileReference section
3116
3117
3118   # Begin PBXFrameworksBuildPhase section
3119   set aTkFrameworks "${theToolKit}_Frameworks"
3120   if { ! [info exists aGuidsMap($aTkFrameworks)] } {
3121     set aGuidsMap($aTkFrameworks) [OS:genGUID "xcd"]
3122   }
3123
3124   puts $aPbxprojFile "\t\t$aGuidsMap($aTkFrameworks) = \{"
3125   puts $aPbxprojFile "\t\t\tisa = PBXFrameworksBuildPhase;"
3126   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3127   puts $aPbxprojFile "\t\t\tfiles = ("
3128   puts $aPbxprojFile $aDepsGuids
3129   puts $aPbxprojFile "\t\t\t);"
3130   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
3131   puts $aPbxprojFile "\t\t\};\n"
3132   # End PBXFrameworksBuildPhase section
3133
3134   # Begin PBXGroup section
3135   set aTkPBXGroup "${theToolKit}_PBXGroup"
3136   if { ! [info exists aGuidsMap($aTkPBXGroup)] } {
3137     set aGuidsMap($aTkPBXGroup) [OS:genGUID "xcd"]
3138   }
3139
3140   set aTkSrcGroup "${theToolKit}_SrcGroup"
3141   if { ! [info exists aGuidsMap($aTkSrcGroup)] } {
3142     set aGuidsMap($aTkSrcGroup) [OS:genGUID "xcd"]
3143   }
3144
3145   puts $aPbxprojFile $aGroupSection
3146   puts $aPbxprojFile "\t\t$aGuidsMap($aTkPBXGroup) = \{"
3147   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
3148   puts $aPbxprojFile "\t\t\tchildren = ("
3149   puts $aPbxprojFile $aDepsRefGuids
3150   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSrcGroup) ,"
3151   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aToolkitLib) ,"
3152   puts $aPbxprojFile "\t\t\t);"
3153   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
3154   puts $aPbxprojFile "\t\t\};"
3155   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSrcGroup) = \{"
3156   puts $aPbxprojFile "\t\t\tisa = PBXGroup;"
3157   puts $aPbxprojFile "\t\t\tchildren = ("
3158   puts $aPbxprojFile $aPackagesGuids
3159   puts $aPbxprojFile "\t\t\t);"
3160   puts $aPbxprojFile "\t\t\tname = \"Source files\";"
3161   puts $aPbxprojFile "\t\t\tsourceTree = \"<group>\";"
3162   puts $aPbxprojFile "\t\t\};\n"
3163   # End PBXGroup section
3164
3165   # Begin PBXHeadersBuildPhase section
3166   set aTkHeaders "${theToolKit}_Headers"
3167   if { ! [info exists aGuidsMap($aTkHeaders)] } {
3168     set aGuidsMap($aTkHeaders) [OS:genGUID "xcd"]
3169   }
3170
3171   puts $aPbxprojFile "\t\t$aGuidsMap($aTkHeaders) = \{"
3172   puts $aPbxprojFile "\t\t\tisa = PBX${aPBXBuildPhase}BuildPhase;"
3173   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3174   puts $aPbxprojFile "\t\t\tfiles = ("
3175   puts $aPbxprojFile "\t\t\t);"
3176   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = ${aRunOnlyForDeployment};"
3177   puts $aPbxprojFile "\t\t\};\n"
3178   # End PBXHeadersBuildPhase section
3179
3180   # Begin PBXNativeTarget section
3181   set aTkBuildCfgListNativeTarget "${theToolKit}_BuildCfgListNativeTarget"
3182   if { ! [info exists aGuidsMap($aTkBuildCfgListNativeTarget)] } {
3183     set aGuidsMap($aTkBuildCfgListNativeTarget) [OS:genGUID "xcd"]
3184   }
3185
3186   set aTkSources "${theToolKit}_Sources"
3187   if { ! [info exists aGuidsMap($aTkSources)] } {
3188     set aGuidsMap($aTkSources) [OS:genGUID "xcd"]
3189   }
3190
3191   puts $aPbxprojFile "\t\t$aGuidsMap($theToolKit) = \{"
3192   puts $aPbxprojFile "\t\t\tisa = PBXNativeTarget;"
3193   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListNativeTarget) ;"
3194   puts $aPbxprojFile "\t\t\tbuildPhases = ("
3195   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkSources) ,"
3196   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkFrameworks) ,"
3197   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkHeaders) ,"
3198   puts $aPbxprojFile "\t\t\t);"
3199   puts $aPbxprojFile "\t\t\tbuildRules = ("
3200   puts $aPbxprojFile "\t\t\t);"
3201   puts $aPbxprojFile "\t\t\tdependencies = ("
3202   puts $aPbxprojFile "\t\t\t);"
3203   puts $aPbxprojFile "\t\t\tname = $theToolKit;"
3204   puts $aPbxprojFile "\t\t\tproductName = $theToolKit;"
3205   puts $aPbxprojFile "\t\t\tproductReference = $aGuidsMap($aToolkitLib) ;"
3206   puts $aPbxprojFile "\t\t\tproductType = \"com.apple.product-type.${aProductType}\";"
3207   puts $aPbxprojFile "\t\t\};\n"
3208   # End PBXNativeTarget section
3209
3210   # Begin PBXProject section
3211   set aTkProjectObj "${theToolKit}_ProjectObj"
3212   if { ! [info exists aGuidsMap($aTkProjectObj)] } {
3213     set aGuidsMap($aTkProjectObj) [OS:genGUID "xcd"]
3214   }
3215
3216   set aTkBuildCfgListProj "${theToolKit}_BuildCfgListProj"
3217   if { ! [info exists aGuidsMap($aTkBuildCfgListProj)] } {
3218     set aGuidsMap($aTkBuildCfgListProj) [OS:genGUID "xcd"]
3219   }
3220
3221   puts $aPbxprojFile "\t\t$aGuidsMap($aTkProjectObj) = \{"
3222   puts $aPbxprojFile "\t\t\tisa = PBXProject;"
3223   puts $aPbxprojFile "\t\t\tattributes = \{"
3224   puts $aPbxprojFile "\t\t\t\tLastUpgradeCheck = 0430;"
3225   puts $aPbxprojFile "\t\t\t\};"
3226   puts $aPbxprojFile "\t\t\tbuildConfigurationList = $aGuidsMap($aTkBuildCfgListProj) ;"
3227   puts $aPbxprojFile "\t\t\tcompatibilityVersion = \"Xcode 3.2\";"
3228   puts $aPbxprojFile "\t\t\tdevelopmentRegion = English;"
3229   puts $aPbxprojFile "\t\t\thasScannedForEncodings = 0;"
3230   puts $aPbxprojFile "\t\t\tknownRegions = ("
3231   puts $aPbxprojFile "\t\t\t\ten,"
3232   puts $aPbxprojFile "\t\t\t);"
3233   puts $aPbxprojFile "\t\t\tmainGroup = $aGuidsMap($aTkPBXGroup);"
3234   puts $aPbxprojFile "\t\t\tproductRefGroup = $aGuidsMap($aTkPBXGroup);"
3235   puts $aPbxprojFile "\t\t\tprojectDirPath = \"\";"
3236   puts $aPbxprojFile "\t\t\tprojectRoot = \"\";"
3237   puts $aPbxprojFile "\t\t\ttargets = ("
3238   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($theToolKit) ,"
3239   puts $aPbxprojFile "\t\t\t);"
3240   puts $aPbxprojFile "\t\t\};\n"
3241   # End PBXProject section
3242
3243   # Begin PBXSourcesBuildPhase section
3244   puts $aPbxprojFile "\t\t$aGuidsMap($aTkSources) = \{"
3245   puts $aPbxprojFile "\t\t\tisa = PBXSourcesBuildPhase;"
3246   puts $aPbxprojFile "\t\t\tbuildActionMask = 2147483647;"
3247   puts $aPbxprojFile "\t\t\tfiles = ("
3248   puts $aPbxprojFile $aSrcFileGuids
3249   puts $aPbxprojFile "\t\t\t);"
3250   puts $aPbxprojFile "\t\t\trunOnlyForDeploymentPostprocessing = 0;"
3251   puts $aPbxprojFile "\t\t\};\n"
3252   # End PBXSourcesBuildPhase section
3253
3254   # Begin XCBuildConfiguration section
3255   set aTkDebugProject "${theToolKit}_DebugProject"
3256   if { ! [info exists aGuidsMap($aTkDebugProject)] } {
3257     set aGuidsMap($aTkDebugProject) [OS:genGUID "xcd"]
3258   }
3259
3260   set aTkReleaseProject "${theToolKit}_ReleaseProject"
3261   if { ! [info exists aGuidsMap($aTkReleaseProject)] } {
3262     set aGuidsMap($aTkReleaseProject) [OS:genGUID "xcd"]
3263   }
3264
3265   set aTkDebugNativeTarget "${theToolKit}_DebugNativeTarget"
3266   if { ! [info exists aGuidsMap($aTkDebugNativeTarget)] } {
3267     set aGuidsMap($aTkDebugNativeTarget) [OS:genGUID "xcd"]
3268   }
3269
3270   set aTkReleaseNativeTarget "${theToolKit}_ReleaseNativeTarget"
3271   if { ! [info exists aGuidsMap($aTkReleaseNativeTarget)] } {
3272     set aGuidsMap($aTkReleaseNativeTarget) [OS:genGUID "xcd"]
3273   }
3274
3275   # Debug target
3276   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugProject) = \{"
3277   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3278   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3279
3280   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;"
3281   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3282   if { "$thePlatform" == "ios" } {
3283     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3284     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3285     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3286     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3287   }
3288   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3289   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3290   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3291   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = NO;"
3292   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3293   puts $aPbxprojFile "\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;"
3294   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3295   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;"
3296   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3297   puts $aPbxprojFile "\t\t\t\t\t\"DEBUG=1\","
3298   puts $aPbxprojFile "\t\t\t\t\t\"\$\(inherited\)\","
3299   puts $aPbxprojFile "\t\t\t\t);"
3300   puts $aPbxprojFile "\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;"
3301   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3302   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3303   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3304   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3305   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3306   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64D)\"; "
3307   if { "$thePlatform" == "ios" } {
3308     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = NO;"
3309     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3310   } else {
3311     puts $aPbxprojFile "\t\t\t\tONLY_ACTIVE_ARCH = YES;"
3312   }
3313   puts $aPbxprojFile "\t\t\t\};"
3314
3315   puts $aPbxprojFile "\t\t\tname = Debug;"
3316   puts $aPbxprojFile "\t\t\};"
3317
3318   # Release target
3319   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseProject) = \{"
3320   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3321   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3322
3323   puts $aPbxprojFile "\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";"
3324   puts $aPbxprojFile "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;"
3325   if { "$thePlatform" == "ios" } {
3326     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphoneos\*\]\" = \"\$(ARCHS_STANDARD)\";";
3327     puts $aPbxprojFile "\t\t\t\t\"ARCHS\[sdk=iphonesimulator\*\]\" = \"x86_64\";";
3328     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_MODULES = YES;"
3329     puts $aPbxprojFile "\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;"
3330   }
3331   puts $aPbxprojFile "\t\t\t\tARCHS = \"\$(ARCHS_STANDARD_64_BIT)\";"
3332   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";"
3333   puts $aPbxprojFile "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++0x\";"
3334   puts $aPbxprojFile "\t\t\t\tCOPY_PHASE_STRIP = YES;"
3335   puts $aPbxprojFile "\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;"
3336   puts $aPbxprojFile "\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;"
3337   puts $aPbxprojFile "\t\t\t\tDEAD_CODE_STRIPPING = NO;"
3338   puts $aPbxprojFile "\t\t\t\tGCC_OPTIMIZATION_LEVEL = 2;"
3339   puts $aPbxprojFile "\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;"
3340   puts $aPbxprojFile "\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;"
3341   puts $aPbxprojFile "\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;"
3342   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;"
3343   puts $aPbxprojFile "\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;"
3344   puts $aPbxprojFile "\t\t\t\tOTHER_LDFLAGS = \"\$(CSF_OPT_LNK64)\";"
3345   if { "$thePlatform" == "ios" } {
3346     puts $aPbxprojFile "\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;"
3347     puts $aPbxprojFile "\t\t\t\tSDKROOT = iphoneos;"
3348   }
3349   puts $aPbxprojFile "\t\t\t\};"
3350   puts $aPbxprojFile "\t\t\tname = Release;"
3351   puts $aPbxprojFile "\t\t\};"
3352   puts $aPbxprojFile "\t\t$aGuidsMap($aTkDebugNativeTarget) = \{"
3353   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3354   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3355   puts $aPbxprojFile "${anExecExtension}"
3356   puts $aPbxprojFile "${anExecPrefix}"
3357   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3358   foreach aMacro $aTKDefines {
3359     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3360   }
3361   puts $aPbxprojFile "\t\t\t\t);"
3362
3363   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3364   foreach anIncPath $anIncPaths {
3365     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3366   }
3367   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3368   puts $aPbxprojFile "\t\t\t\t);"
3369
3370   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3371   foreach anLibPath $anLibPaths {
3372     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3373   }
3374   puts $aPbxprojFile "\t\t\t\t);"
3375
3376   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3377   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3378   puts $aPbxprojFile "\t\t\t\t);"
3379   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3380   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3381   puts $aPbxprojFile "\t\t\t\t);"
3382   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3383   set anUserHeaderSearchPath "\t\t\t\tUSER_HEADER_SEARCH_PATHS = \""
3384   foreach anIncPath $anIncPaths {
3385     append anUserHeaderSearchPath " ${anIncPath}"
3386   }
3387   append anUserHeaderSearchPath "\";"
3388   puts $aPbxprojFile $anUserHeaderSearchPath
3389   puts $aPbxprojFile "${aWrapperExtension}"
3390   puts $aPbxprojFile "\t\t\t\};"
3391   puts $aPbxprojFile "\t\t\tname = Debug;"
3392   puts $aPbxprojFile "\t\t\};"
3393   puts $aPbxprojFile "\t\t$aGuidsMap($aTkReleaseNativeTarget) = \{"
3394   puts $aPbxprojFile "\t\t\tisa = XCBuildConfiguration;"
3395   puts $aPbxprojFile "\t\t\tbuildSettings = \{"
3396   puts $aPbxprojFile "${anExecExtension}"
3397   puts $aPbxprojFile "${anExecPrefix}"
3398   puts $aPbxprojFile "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ("
3399   foreach aMacro $aTKDefines {
3400     puts $aPbxprojFile "\t\t\t\t\t${aMacro} ,"
3401   }
3402   puts $aPbxprojFile "\t\t\t\t);"
3403   puts $aPbxprojFile "\t\t\t\tHEADER_SEARCH_PATHS = ("
3404   foreach anIncPath $anIncPaths {
3405     puts $aPbxprojFile "\t\t\t\t\t${anIncPath},"
3406   }
3407   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_INC)\","
3408   puts $aPbxprojFile "\t\t\t\t);"
3409
3410   puts $aPbxprojFile "\t\t\t\tLIBRARY_SEARCH_PATHS = ("
3411   foreach anLibPath $anLibPaths {
3412     puts $aPbxprojFile "\t\t\t\t\t${anLibPath},"
3413   }
3414   puts $aPbxprojFile "\t\t\t\t);"
3415
3416   puts $aPbxprojFile "\t\t\t\tOTHER_CFLAGS = ("
3417   puts $aPbxprojFile "\t\t\t\t\t\"\$(CSF_OPT_CMPL)\","
3418   puts $aPbxprojFile "\t\t\t\t);"
3419   puts $aPbxprojFile "\t\t\t\tOTHER_CPLUSPLUSFLAGS = ("
3420   puts $aPbxprojFile "\t\t\t\t\t\"\$(OTHER_CFLAGS)\","
3421   puts $aPbxprojFile "\t\t\t\t);"
3422   puts $aPbxprojFile "\t\t\t\tPRODUCT_NAME = \"\$(TARGET_NAME)\";"
3423   puts $aPbxprojFile $anUserHeaderSearchPath
3424   puts $aPbxprojFile "${aWrapperExtension}"
3425   puts $aPbxprojFile "\t\t\t\};"
3426   puts $aPbxprojFile "\t\t\tname = Release;"
3427   puts $aPbxprojFile "\t\t\};\n"
3428   # End XCBuildConfiguration section
3429
3430   # Begin XCConfigurationList section
3431   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListProj) = \{"
3432   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3433   puts $aPbxprojFile "\t\tbuildConfigurations = ("
3434   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugProject) ,"
3435   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseProject) ,"
3436   puts $aPbxprojFile "\t\t\t);"
3437   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3438   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3439   puts $aPbxprojFile "\t\t\};"
3440   puts $aPbxprojFile "\t\t$aGuidsMap($aTkBuildCfgListNativeTarget) = \{"
3441   puts $aPbxprojFile "\t\t\tisa = XCConfigurationList;"
3442   puts $aPbxprojFile "\t\t\tbuildConfigurations = ("
3443   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkDebugNativeTarget) ,"
3444   puts $aPbxprojFile "\t\t\t\t$aGuidsMap($aTkReleaseNativeTarget) ,"
3445   puts $aPbxprojFile "\t\t\t);"
3446   puts $aPbxprojFile "\t\t\tdefaultConfigurationIsVisible = 0;"
3447   puts $aPbxprojFile "\t\t\tdefaultConfigurationName = Release;"
3448   puts $aPbxprojFile "\t\t\};\n"
3449   # End XCConfigurationList section
3450
3451   puts $aPbxprojFile "\t\};"
3452   puts $aPbxprojFile "\trootObject = $aGuidsMap($aTkProjectObj) ;"
3453   puts $aPbxprojFile "\}"
3454
3455   close $aPbxprojFile
3456 }
3457
3458 proc osutils:xcdx { theOutDir theExecutable theGuidsMap } {
3459   set aUsername [exec whoami]
3460
3461   # Creating folders for Xcode project file.
3462   set anExecutableDir "${theOutDir}/${theExecutable}.xcodeproj"
3463   wokUtils:FILES:mkdir $anExecutableDir
3464   if { ! [file exists $anExecutableDir] } {
3465     puts stderr "Error: Could not create project directory \"$anExecutableDir\""
3466     return
3467   }
3468
3469   set aUserDataDir "${anExecutableDir}/xcuserdata"
3470   wokUtils:FILES:mkdir $aUserDataDir
3471   if { ! [file exists $aUserDataDir] } {
3472     puts stderr "Error: Could not create xcuserdata directorty in \"$anExecutableDir\""
3473     return
3474   }
3475
3476   set aUserDataDir "${aUserDataDir}/${aUsername}.xcuserdatad"
3477   wokUtils:FILES:mkdir $aUserDataDir
3478   if { ! [file exists $aUserDataDir] } {
3479     puts stderr "Error: Could not create ${aUsername}.xcuserdatad directorty in \"$anExecutableDir\"/xcuserdata"
3480     return
3481   }
3482
3483   set aSchemesDir "${aUserDataDir}/xcschemes"
3484   wokUtils:FILES:mkdir $aSchemesDir
3485   if { ! [file exists $aSchemesDir] } {
3486     puts stderr "Error: Could not create xcschemes directorty in \"$aUserDataDir\""
3487     return
3488   }
3489   # End folders creation.
3490
3491   # Generating GUID for tookit.
3492   upvar $theGuidsMap aGuidsMap
3493   if { ! [info exists aGuidsMap($theExecutable)] } {
3494     set aGuidsMap($theExecutable) [OS:genGUID "xcd"]
3495   }
3496
3497   # Creating xcscheme file for toolkit from template.
3498   set aXcschemeTmpl [osutils:readtemplate "xcscheme" "xcode"]
3499   regsub -all -- {__TOOLKIT_NAME__} $aXcschemeTmpl $theExecutable aXcschemeTmpl
3500   regsub -all -- {__TOOLKIT_GUID__} $aXcschemeTmpl $aGuidsMap($theExecutable) aXcschemeTmpl
3501   set aXcschemeFile [open "$aSchemesDir/${theExecutable}.xcscheme"  "w"]
3502   puts $aXcschemeFile $aXcschemeTmpl
3503   close $aXcschemeFile
3504
3505   # Creating xcschememanagement.plist file for toolkit from template.
3506   set aPlistTmpl [osutils:readtemplate "plist" "xcode"]
3507   regsub -all -- {__TOOLKIT_NAME__} $aPlistTmpl $theExecutable aPlistTmpl
3508   regsub -all -- {__TOOLKIT_GUID__} $aPlistTmpl $aGuidsMap($theExecutable) aPlistTmpl
3509   set aPlistFile [open "$aSchemesDir/xcschememanagement.plist"  "w"]
3510   puts $aPlistFile $aPlistTmpl
3511   close $aPlistFile
3512 }
3513
3514 # Returns available Windows SDKs versions
3515 proc osutils:sdk { theSdkMajorVer {isQuietMode false} {theSdkDirectories {}} } {
3516   if { ![llength ${theSdkDirectories}] } {
3517     foreach anEnvVar { "ProgramFiles" "ProgramFiles\(x86\)" "ProgramW6432" } {
3518       if {[ info exists ::env(${anEnvVar}) ]} {
3519         lappend theSdkDirectories "$::env(${anEnvVar})/Windows Kits/${theSdkMajorVer}/Include"
3520       }
3521     }
3522   }
3523
3524   set sdk_versions {}
3525   foreach sdk_dir ${theSdkDirectories} {
3526     if { [file isdirectory ${sdk_dir}] } {
3527       lappend sdk_versions [glob -tails -directory "${sdk_dir}" -type d *]
3528     }
3529   }
3530
3531   if {![llength ${sdk_versions}] && !${isQuietMode}} {
3532     error "Error : Could not find Windows SDK ${theSdkMajorVer}"
3533   }
3534
3535   return [join [lsort -unique ${sdk_versions}] " "]
3536 }
3537
3538 # Generate global properties to Visual Studio project file for UWP solution
3539 proc osutils:uwp:proj { isUWP theProjTmpl } {
3540
3541   set uwp_properties ""
3542   set uwp_generate_metadata ""
3543   set uwp_app_container ""
3544
3545   set format_template ""
3546
3547   if { $isUWP } {
3548     set sdk_versions [osutils:sdk 10]
3549     set sdk_max_ver [lindex ${sdk_versions} end]
3550
3551     set uwp_properties "<DefaultLanguage>en-US</DefaultLanguage>\n   \
3552 <ApplicationType>Windows Store</ApplicationType>\n   \
3553 <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\n   \
3554 <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\n   \
3555 <AppContainerApplication>true</AppContainerApplication>\n   \
3556 <WindowsTargetPlatformVersion>${sdk_max_ver}</WindowsTargetPlatformVersion>\n   \
3557 <WindowsTargetPlatformMinVersion>${sdk_max_ver}</WindowsTargetPlatformMinVersion>"
3558
3559     set uwp_generate_metadata        "<GenerateWindowsMetadata>false</GenerateWindowsMetadata>"
3560
3561     regsub -all -- {[\r\n\s]*<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>} ${theProjTmpl} "" theProjTmpl
3562   } else {
3563     set format_template "\[\\r\\n\\s\]*"
3564   }
3565
3566   regsub -all -- "${format_template}__UWP_PROPERTIES__"        ${theProjTmpl} "${uwp_properties}" theProjTmpl
3567   regsub -all -- "${format_template}__UWP_GENERATE_METADATA__" ${theProjTmpl} "${uwp_generate_metadata}" theProjTmpl
3568
3569   return ${theProjTmpl}
3570 }
3571
3572 # Report all files found in package directory but not listed in FILES
3573 proc osutils:checksrcfiles { theUnit theSrcDir} {
3574   global path
3575   set aCasRoot [file normalize ${path}]
3576
3577   if {![file isdirectory ${aCasRoot}]} {
3578     puts "OCCT directory is not defined correctly: ${aCasRoot}"
3579     return
3580   }
3581
3582   set anUnitAbsPath [file normalize "${aCasRoot}/$theSrcDir/${theUnit}"]
3583
3584   if {[file exists "${anUnitAbsPath}/FILES"]} {
3585     set aFilesFile [open "${anUnitAbsPath}/FILES" rb]
3586     set aFilesFileList [split [read ${aFilesFile}] "\n"]
3587     close ${aFilesFile}
3588
3589     set aFilesFileList [lsearch -inline -all -not -exact ${aFilesFileList} ""]
3590
3591     # report all files not listed in FILES
3592     set anAllFiles [glob -tails -nocomplain -dir ${anUnitAbsPath} "*"]
3593     foreach aFile ${anAllFiles} {
3594       if { "${aFile}" == "FILES" } {
3595         continue
3596       }
3597       if { "${aFile}" == "icons" } {
3598         continue
3599       }
3600       if { [lsearch -exact ${aFilesFileList} ${aFile}] == -1 } {
3601         puts "Warning: file ${anUnitAbsPath}/${aFile} is not listed in ${anUnitAbsPath}/FILES!"
3602       }
3603     }
3604   }
3605 }