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