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