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