0030966: Configuration, genproj.tcl - look for an optional libraries e57 and xerces
[occt.git] / adm / genconfdeps.tcl
1 # =======================================================================
2 # Created on: 2012-01-26
3 # Created by: Kirill GAVRILOV
4 # Copyright (c) 2012 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 # Tools for search of third-party libraries and generation on environment
19 # customization script
20 # =======================================================================
21
22 set ARCH "64"
23
24 if { "$tcl_platform(platform)" == "unix" } {
25   set SYS_PATH_SPLITTER ":"
26   set SYS_LIB_PREFIX    "lib"
27   set SYS_EXE_SUFFIX    ""
28   if { "$tcl_platform(os)" == "Darwin" } {
29     set SYS_LIB_SUFFIX "dylib"
30     set PRJFMT "xcd"
31   } else {
32     set SYS_LIB_SUFFIX "so"
33     set PRJFMT "cbp"
34   }
35   set VCVER "gcc"
36   set VCVARS ""
37 } elseif { "$tcl_platform(platform)" == "windows" } {
38   set SYS_PATH_SPLITTER ";"
39   set SYS_LIB_PREFIX    ""
40   set SYS_LIB_SUFFIX    "lib"
41   set SYS_EXE_SUFFIX    ".exe"
42   set VCVER  "vc10"
43   set VCVARS ""
44   set PRJFMT "vcxproj"
45 }
46
47 set SHORTCUT_HEADERS "ShortCut"
48
49 set PRODUCTS_PATH ""
50 set CSF_OPT_INC   [list]
51 set CSF_OPT_LIB32 [list]
52 set CSF_OPT_LIB64 [list]
53 set CSF_OPT_BIN32 [list]
54 set CSF_OPT_BIN64 [list]
55
56 if { "$tcl_platform(pointerSize)" == "4" } {
57   set ARCH "32"
58 }
59 if { [info exists ::env(ARCH)] } {
60   set ARCH "$::env(ARCH)"
61 }
62
63 if { [info exists ::env(SHORTCUT_HEADERS)] } {
64   set SHORTCUT_HEADERS "$::env(SHORTCUT_HEADERS)"
65   if { $SHORTCUT_HEADERS == "true" } {
66     set SHORTCUT_HEADERS "ShortCut"
67   }
68 }
69
70 # fetch environment variables (e.g. set by custom.sh or custom.bat) and set them as tcl variables with the same name
71 set THE_ENV_VARIABLES {HAVE_FREEIMAGE HAVE_FFMPEG HAVE_TBB HAVE_GLES2 HAVE_D3D HAVE_VTK HAVE_ZLIB HAVE_LIBLZMA HAVE_E57 HAVE_RAPIDJSON HAVE_OPENCL CHECK_QT4 CHECK_JDK MACOSX_USE_GLX HAVE_RelWithDebInfo}
72 foreach anEnvIter $THE_ENV_VARIABLES {
73   set ${anEnvIter} "false"
74   if { [info exists ::env(${anEnvIter})] } {
75     set ${anEnvIter} "$::env(${anEnvIter})"
76   }
77 }
78 # do not export platform-specific variables
79 if { "$::tcl_platform(os)" == "Darwin" } {
80   set HAVE_GLES2 ""
81 } else {
82   set MACOSX_USE_GLX ""
83 }
84 if { "$tcl_platform(platform)" != "windows" } {
85   set HAVE_D3D ""
86   set HAVE_RelWithDebInfo ""
87 }
88 foreach anEnvIter {ARCH VCVER VCVARS PRJFMT } {
89   if { [info exists ::env(${anEnvIter})] } {
90     set ${anEnvIter} "$::env(${anEnvIter})"
91   }
92 }
93 if { [info exists ::env(PRODUCTS_PATH)] } {
94   set PRODUCTS_PATH [file normalize "$::env(PRODUCTS_PATH)"]
95 }
96
97 if { [info exists ::env(CSF_OPT_INC)] } {
98   set CSF_OPT_INC [split "$::env(CSF_OPT_INC)" $::SYS_PATH_SPLITTER]
99 }
100 if { [info exists ::env(CSF_OPT_LIB32)] } {
101   set CSF_OPT_LIB32 [split "$::env(CSF_OPT_LIB32)" $::SYS_PATH_SPLITTER]
102 }
103 if { [info exists ::env(CSF_OPT_LIB64)] } {
104   set CSF_OPT_LIB64 [split "$::env(CSF_OPT_LIB64)" $::SYS_PATH_SPLITTER]
105 }
106 if { [info exists ::env(CSF_OPT_BIN32)] } {
107   set CSF_OPT_BIN32 [split "$::env(CSF_OPT_BIN32)" $::SYS_PATH_SPLITTER]
108 }
109 if { [info exists ::env(CSF_OPT_BIN64)] } {
110   set CSF_OPT_BIN64 [split "$::env(CSF_OPT_BIN64)" $::SYS_PATH_SPLITTER]
111 }
112
113 # Search header file in $::CSF_OPT_INC and standard paths
114 proc wokdep:SearchHeader {theHeader} {
115   # search in custom paths
116   foreach anIncPath $::CSF_OPT_INC {
117     set aPath "${anIncPath}/${theHeader}"
118     if { [file exists "$aPath"] } {
119       return "$aPath"
120     }
121   }
122
123   # search in system
124   set aPath "/usr/include/${theHeader}"
125   if { [file exists "$aPath"] } {
126     return "$aPath"
127   }
128
129   if { "$::tcl_platform(os)" == "Linux" } {
130     if { "$::ARCH" == "64" } {
131       set aPath "/usr/include/x86_64-linux-gnu/${theHeader}"
132       if { [file exists "$aPath"] } {
133         return "$aPath"
134       }
135     } else {
136       set aPath "/usr/include/i386-linux-gnu/${theHeader}"
137       if { [file exists "$aPath"] } {
138         return "$aPath"
139       }
140     }
141   }
142
143   return ""
144 }
145
146 # Search library file in $::CSF_OPT_LIB* and standard paths
147 proc wokdep:SearchLib {theLib theBitness {theSearchPath ""}} {
148   if { "$theSearchPath" != "" } {
149     set aPath  "${theSearchPath}/${::SYS_LIB_PREFIX}${theLib}.${::SYS_LIB_SUFFIX}"
150     set aPath2 "${theSearchPath}/${::SYS_LIB_PREFIX}${theLib}.a"
151     if { [file exists "$aPath"] } {
152       return "$aPath"
153     } elseif { "$::tcl_platform(platform)" != "windows" && [file exists "$aPath2"] } {
154       return "$aPath2"
155     } else {
156       return ""
157     }
158   }
159
160   # search in custom paths
161   foreach aLibPath [set ::CSF_OPT_LIB$theBitness] {
162     set aPath  "${aLibPath}/${::SYS_LIB_PREFIX}${theLib}.${::SYS_LIB_SUFFIX}"
163     set aPath2 "${aLibPath}/${::SYS_LIB_PREFIX}${theLib}.a"
164     if { [file exists "$aPath"] } {
165       return "$aPath"
166     } elseif { "$::tcl_platform(platform)" != "windows" && [file exists "$aPath2"] } {
167       return "$aPath2"
168     }
169   }
170
171   # search in system
172   if { "$::ARCH" == "$theBitness"} {
173     set aPath  "/usr/lib/${::SYS_LIB_PREFIX}${theLib}.${::SYS_LIB_SUFFIX}"
174     set aPath2 "/usr/lib/${::SYS_LIB_PREFIX}${theLib}.a"
175     if { [file exists "$aPath"] } {
176       return "$aPath"
177     } elseif { [file exists "$aPath2"] } {
178       return "$aPath2"
179     }
180   }
181
182   if { "$::tcl_platform(os)" == "Linux" } {
183     if { "$theBitness" == "64" } {
184       set aPath  "/usr/lib/x86_64-linux-gnu/lib${theLib}.so"
185       set aPath2 "/usr/lib/x86_64-linux-gnu/lib${theLib}.a"
186       if { [file exists "$aPath"] } {
187         return "$aPath"
188       } elseif { [file exists "$aPath2"] } {
189         return "$aPath2"
190       }
191     } else {
192       set aPath  "/usr/lib/i386-linux-gnu/lib${theLib}.so"
193       set aPath2 "/usr/lib/i386-linux-gnu/lib${theLib}.a"
194       if { [file exists "$aPath"] } {
195         return "$aPath"
196       } elseif { [file exists "$aPath2"] } {
197         return "$aPath2"
198       }
199     }
200   }
201
202   return ""
203 }
204
205 # Search file in $::CSF_OPT_BIN* and standard paths
206 proc wokdep:SearchBin {theBin theBitness {theSearchPath ""}} {
207   if { "$theSearchPath" != "" } {
208     set aPath "${theSearchPath}/${theBin}"
209     if { [file exists "$aPath"] } {
210       return "$aPath"
211     } else {
212       return ""
213     }
214   }
215
216   # search in custom paths
217   foreach aBinPath [set ::CSF_OPT_BIN$theBitness] {
218     set aPath "${aBinPath}/${theBin}"
219     if { [file exists "$aPath"] } {
220       return "$aPath"
221     }
222   }
223
224   # search in system
225   if { "$::ARCH" == "$theBitness"} {
226     set aPath "/usr/bin/${theBin}"
227     if { [file exists "$aPath"] } {
228       return "$aPath"
229     }
230   }
231
232   return ""
233 }
234
235 # Detect compiler C-runtime version 'vc*' and architecture '32'/'64'
236 # to determine preferred path.
237 proc wokdep:Preferred {theList theCmpl theArch} {
238   if { [llength $theList] == 0 } {
239     return ""
240   }
241
242   # keep only two first digits in "vc141"
243   if { ! [regexp {^vc[0-9][0-9]} $theCmpl aCmpl] } {
244     set aCmpl $theCmpl
245   }
246
247   set aShortList {}
248   foreach aPath $theList {
249     if { [string first "$aCmpl" "$aPath"] != "-1" } {
250       lappend aShortList "$aPath"
251     }
252   }
253
254   if { [llength $aShortList] == 0 } {
255     #return [lindex $theList 0]
256     set aShortList $theList
257   }
258
259   set aVeryShortList {}
260   foreach aPath $aShortList {
261     if { [string first "$theArch" "$aPath"] != "-1" } {
262       lappend aVeryShortList "$aPath"
263     }
264   }
265   if { [llength $aVeryShortList] == 0 } {
266     return [lindex [lsort -decreasing $aShortList] 0]
267   }
268
269   return [lindex [lsort -decreasing $aVeryShortList] 0]
270 }
271
272 # Search library placement
273 proc wokdep:SearchStandardLibrary {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64 theName theCheckHeader theCheckLib theCheckFolders} {
274   upvar $theErrInc   anErrInc
275   upvar $theErrLib32 anErrLib32
276   upvar $theErrLib64 anErrLib64
277   upvar $theErrBin32 anErrBin32
278   upvar $theErrBin64 anErrBin64
279
280   set isFound "true"
281   set aHeaderPath [wokdep:SearchHeader "$theCheckHeader"]
282   if { "$aHeaderPath"  == "" } {
283     set hasHeader false
284     foreach aFolderIter $theCheckFolders {
285       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{$aFolderIter}*] "$::VCVER" "$::ARCH" ]
286       if { "$aPath" != "" && [file exists "$aPath/include/$theCheckHeader"] } {
287         lappend ::CSF_OPT_INC "$aPath/include"
288         set hasHeader true
289         break
290       }
291     }
292     if { !$hasHeader } {
293       lappend anErrInc "Error: '$theCheckHeader' not found ($theName)"
294       set isFound "false"
295     }
296   }
297
298   foreach anArchIter {64 32} {
299     set aLibPath [wokdep:SearchLib "$theCheckLib" "$anArchIter"]
300     if { "$aLibPath" == "" } {
301       set hasLib false
302       foreach aFolderIter $theCheckFolders {
303         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{$aFolderIter}*] "$::VCVER" "$anArchIter" ]
304         set aLibPath [wokdep:SearchLib "$theCheckLib" "$anArchIter" "$aPath/lib"]
305         if { "$aLibPath" != "" } {
306           lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
307           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
308           set hasLib true
309           break
310         }
311       }
312       if { !$hasLib } {
313         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}$theCheckLib.${::SYS_LIB_SUFFIX}' not found ($theName)"
314         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
315       }
316     }
317
318     if { "$::tcl_platform(platform)" == "windows" } {
319       set aDllPath [wokdep:SearchBin "$theCheckLib.dll" "$anArchIter"]
320       if { "$aDllPath" == "" } {
321         set hasDll false
322         foreach aFolderIter $theCheckFolders {
323           set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{$aFolderIter}*] "$::VCVER" "$anArchIter" ]
324           set aDllPath [wokdep:SearchBin "$theCheckLib.dll" "$anArchIter" "$aPath/bin"]
325           if { "$aDllPath" != "" } {
326             lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
327             set hasDll true
328             break
329           } else {
330             set aDllPath [wokdep:SearchBin "$theCheckLib.dll" "$anArchIter" "$aPath/lib"]
331             if { "$aDllPath" != "" } {
332               lappend ::CSF_OPT_BIN$anArchIter "$aPath/lib"
333               set hasDll true
334               break
335             }
336           }
337         }
338         if { !$hasDll } {
339           lappend anErrBin$anArchIter "Error: '$theCheckLib.dll' not found ($theName)"
340           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
341         }
342       }
343     }
344   }
345
346   return "$isFound"
347 }
348
349 # Search Tcl/Tk libraries placement
350 proc wokdep:SearchTclTk {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
351   upvar $theErrInc   anErrInc
352   upvar $theErrLib32 anErrLib32
353   upvar $theErrLib64 anErrLib64
354   upvar $theErrBin32 anErrBin32
355   upvar $theErrBin64 anErrBin64
356
357   set tclver_maj 8
358   set tclver_min 6
359   
360   set isFound "true"
361   set aTclHPath [wokdep:SearchHeader "tcl.h"]
362   set aTkHPath  [wokdep:SearchHeader "tk.h"]
363   if { "$aTclHPath" == "" || "$aTkHPath" == "" } {
364     if { [file exists "/usr/include/tcl8.6/tcl.h"]
365       && [file exists "/usr/include/tcl8.6/tk.h" ] } {
366       lappend ::CSF_OPT_INC "/usr/include/tcl8.6"
367       set aTclHPath "/usr/include/tcl8.6/tcl.h"
368     } else {
369       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{tcl}*] "$::VCVER" "$::ARCH" ]
370       if { "$aPath" != "" && [file exists "$aPath/include/tcl.h"] && [file exists "$aPath/include/tk.h"] } {
371         lappend ::CSF_OPT_INC "$aPath/include"
372         set aTclHPath "$aPath/include/tcl.h"
373       } else {
374         lappend anErrInc "Error: 'tcl.h' or 'tk.h' not found (Tcl/Tk)"
375         set isFound "false"
376       }
377     }
378   }
379
380   # detect tcl version by parsing header file
381   if { $isFound } {
382     set fh [open $aTclHPath]
383     set tcl_h [read $fh]
384     close $fh
385     regexp {define\s+TCL_MAJOR_VERSION\s+([0-9]+)} $tcl_h dummy tclver_maj
386     regexp {define\s+TCL_MINOR_VERSION\s+([0-9]+)} $tcl_h dummy tclver_min
387   }
388
389   if { "$::tcl_platform(platform)" == "windows" } {
390     set aTclLibName "tcl${tclver_maj}${tclver_min}"
391     set aTkLibName  "tk${tclver_maj}${tclver_min}"
392   } else {
393     set aTclLibName "tcl${tclver_maj}.${tclver_min}"
394     set aTkLibName  "tk${tclver_maj}.${tclver_min}"
395   }
396
397   foreach anArchIter {64 32} {
398     set aTclLibPath [wokdep:SearchLib "$aTclLibName" "$anArchIter"]
399     set aTkLibPath  [wokdep:SearchLib "$aTkLibName"  "$anArchIter"]
400     if { "$aTclLibPath" == "" || "$aTkLibPath" == "" } {
401       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{tcl}*] "$::VCVER" "$anArchIter" ]
402       set aTclLibPath [wokdep:SearchLib "$aTclLibName" "$anArchIter" "$aPath/lib"]
403       set aTkLibPath  [wokdep:SearchLib "$aTkLibName"  "$anArchIter" "$aPath/lib"]
404       if { "$aTclLibPath" != "" && "$aTkLibPath" != "" } {
405         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
406       } else {
407         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}${aTclLibName}.${::SYS_LIB_SUFFIX}' or '${::SYS_LIB_PREFIX}${aTkLibName}.${::SYS_LIB_SUFFIX}' not found (Tcl/Tk)"
408         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
409       }
410     }
411
412     if { "$::tcl_platform(platform)" == "windows" } {
413       set aTclDllPath [wokdep:SearchBin "${aTclLibName}.dll" "$anArchIter"]
414       set aTkDllPath  [wokdep:SearchBin "${aTkLibName}.dll"  "$anArchIter"]
415       if { "$aTclDllPath" == "" || "$aTkDllPath" == "" } {
416         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{tcl}*] "$::VCVER" "$anArchIter" ]
417         set aTclDllPath [wokdep:SearchBin "${aTclLibName}.dll" "$anArchIter" "$aPath/bin"]
418         set aTkDllPath  [wokdep:SearchBin "${aTkLibName}.dll"  "$anArchIter" "$aPath/bin"]
419         if { "$aTclDllPath" != "" && "$aTkDllPath" != "" } {
420           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
421         } else {
422           lappend anErrBin$anArchIter "Error: '${aTclLibName}.dll' or '${aTkLibName}.dll' not found (Tcl/Tk)"
423           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
424         }
425       }
426     }
427   }
428
429   return "$isFound"
430 }
431
432 # Search FreeType library placement
433 proc wokdep:SearchFreeType {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
434   upvar $theErrInc   anErrInc
435   upvar $theErrLib32 anErrLib32
436   upvar $theErrLib64 anErrLib64
437   upvar $theErrBin32 anErrBin32
438   upvar $theErrBin64 anErrBin64
439
440   set isFound "true"
441   set aFtBuildPath [wokdep:SearchHeader "ft2build.h"]
442
443   if { "$aFtBuildPath" == "" } {
444     # TODO - use `freetype-config --cflags` instead
445     set aSysFreeType "/usr/include/freetype2"
446     if { [file exists "$aSysFreeType/ft2build.h"] } {
447       lappend ::CSF_OPT_INC "$aSysFreeType"
448     } elseif { [file exists "$aSysFreeType/freetype2/ft2build.h"] } {
449       lappend ::CSF_OPT_INC "$aSysFreeType/freetype2"
450     } else {
451       set aSysFreeType "/usr/X11/include/freetype2"
452       if { [file exists "$aSysFreeType/ft2build.h"] } {
453         lappend ::CSF_OPT_INC "/usr/X11/include"
454         lappend ::CSF_OPT_INC "$aSysFreeType"
455       } else {
456         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{freetype}*] "$::VCVER" "$::ARCH" ]
457         if {"$aPath" != ""} {
458           if {[file exists "$aPath/include/ft2build.h"]} {
459             lappend ::CSF_OPT_INC "$aPath/include"
460           } elseif {[file exists "$aPath/include/freetype2/ft2build.h"]} {
461             lappend ::CSF_OPT_INC "$aPath/include/freetype2"
462           }
463         } else {
464           lappend anErrInc "Error: 'freetype.h' not found (FreeType2)"
465           set isFound "false"
466         }
467       }
468     }
469   }
470
471   # parse 'freetype-config --libs'
472   set aConfLibPath ""
473   if { [catch { set aConfLibs [exec freetype-config --libs] } ] == 0 } {
474     foreach aPath [split $aConfLibs " "] {
475       if { [string first "-L" "$aPath"] == 0 } {
476         set aConfLibPath [string range "$aPath" 2 [string length "$aPath"]]
477       }
478     }
479   }
480
481   foreach anArchIter {64 32} {
482     set aFtLibPath [wokdep:SearchLib "freetype" "$anArchIter"]
483     if { "$aFtLibPath" == "" } {
484       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{freetype}*] "$::VCVER" "$anArchIter" ]
485       set aFtLibPath [wokdep:SearchLib "freetype" "$anArchIter" "$aPath/lib"]
486       if { "$aFtLibPath" != "" } {
487         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
488       } else {
489         set aFtLibPath [wokdep:SearchLib "freetype" "$anArchIter" "$aConfLibPath"]
490         if { "$aFtLibPath" != "" } {
491           lappend ::CSF_OPT_LIB$anArchIter "$aConfLibPath"
492         } else {
493           lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}freetype.${::SYS_LIB_SUFFIX}' not found (FreeType2)"
494           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
495         }
496       }
497     }
498     if { "$::tcl_platform(platform)" == "windows" } {
499       set aFtDllPath [wokdep:SearchBin "freetype.dll" "$anArchIter"]
500       if { "$aFtDllPath" == "" } {
501         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{freetype}*] "$::VCVER" "$anArchIter" ]
502         set aFtDllPath [wokdep:SearchBin "freetype.dll" "$anArchIter" "$aPath/bin"]
503         if { "$aFtDllPath" != "" } {
504           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
505         } else {
506           set aFtDllPath [wokdep:SearchBin "freetype.dll" "$anArchIter" "$aPath/lib"]
507           if { "$aFtDllPath" != "" } {
508             lappend ::CSF_OPT_BIN$anArchIter "$aPath/lib"
509           } else {
510             lappend anErrBin$anArchIter "Error: 'freetype.dll' not found (FreeType2)"
511             if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
512           }
513         }
514       }
515     }
516   }
517
518   return "$isFound"
519 }
520
521 # Search FreeImage library placement
522 proc wokdep:SearchFreeImage {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
523   upvar $theErrInc   anErrInc
524   upvar $theErrLib32 anErrLib32
525   upvar $theErrLib64 anErrLib64
526   upvar $theErrBin32 anErrBin32
527   upvar $theErrBin64 anErrBin64
528
529   # binary distribution has another layout
530   set aFImageDist     "Dist"
531
532   set isFound "true"
533   set aFImageHPath [wokdep:SearchHeader "FreeImage.h"]
534   if { "$aFImageHPath" == "" } {
535     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{freeimage}*] "$::VCVER" "$::ARCH" ]
536     if { "$aPath" != "" && [file exists "$aPath/include/FreeImage.h"] } {
537       lappend ::CSF_OPT_INC "$aPath/include"
538     } elseif { "$aPath" != "" && [file exists "$aPath/$aFImageDist/FreeImage.h"] } {
539       lappend ::CSF_OPT_INC "$aPath/$aFImageDist"
540     } else {
541       lappend anErrInc "Error: 'FreeImage.h' not found (FreeImage)"
542       set isFound "false"
543     }
544   }
545
546   foreach anArchIter {64 32} {
547     set aFImageLibPath [wokdep:SearchLib "freeimage"     "$anArchIter"]
548     if { "$aFImageLibPath" == "" } {
549       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{freeimage}*] "$::VCVER" "$anArchIter" ]
550       set aFImageLibPath [wokdep:SearchLib "freeimage" "$anArchIter" "$aPath/lib"]
551       if { "$aFImageLibPath" != "" } {
552         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
553       } else {
554         set aFImageLibPath [wokdep:SearchLib "freeimage" "$anArchIter" "$aPath/$aFImageDist"]
555         if { "$aFImageLibPath" != "" } {
556           lappend ::CSF_OPT_LIB$anArchIter "$aPath/$aFImageDist"
557         } else {
558           lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}freeimage.${::SYS_LIB_SUFFIX}' not found (FreeImage)"
559           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
560         }
561       }
562     }
563     if { "$::tcl_platform(platform)" == "windows" } {
564       set aFImageDllPath [wokdep:SearchBin "freeimage.dll" "$anArchIter"]
565       if { "$aFImageDllPath" == "" } {
566         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{freeimage}*] "$::VCVER" "$anArchIter" ]
567         set aFImageDllPath [wokdep:SearchBin "freeimage.dll" "$anArchIter" "$aPath/bin"]
568         if { "$aFImageDllPath" != "" } {
569           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
570         } else {
571           set aFImageDllPath [wokdep:SearchBin "freeimage.dll" "$anArchIter" "$aPath/$aFImageDist"]
572           if { "$aFImageDllPath" != "" } {
573             lappend ::CSF_OPT_BIN$anArchIter "$aPath/$aFImageDist"
574           } else {
575             lappend anErrBin$anArchIter "Error: 'freeimage.dll' is not found (FreeImage)"
576             if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
577           }
578         }
579       }
580     }
581   }
582
583   return "$isFound"
584 }
585
586 # Search FFmpeg framework placement
587 proc wokdep:SearchFFmpeg {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
588   upvar $theErrInc   anErrInc
589   upvar $theErrLib32 anErrLib32
590   upvar $theErrLib64 anErrLib64
591   upvar $theErrBin32 anErrBin32
592   upvar $theErrBin64 anErrBin64
593
594   set isFound "true"
595   set aFFmpegHPath [wokdep:SearchHeader "libavutil/avutil.h"]
596   if { "$aFFmpegHPath"  == "" } {
597     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{ffmpeg}*] "$::VCVER" "$::ARCH" ]
598     if { "$aPath" != "" && [file exists "$aPath/include/libavutil/avutil.h"] } {
599       lappend ::CSF_OPT_INC "$aPath/include"
600     } else {
601       lappend anErrInc "Error: 'libavutil/avutil.h' not found (FFmpeg)"
602       set isFound "false"
603     }
604   }
605
606   foreach anArchIter {64 32} {
607     set aFFmpegLibPath [wokdep:SearchLib "avutil" "$anArchIter"]
608     if { "$aFFmpegLibPath" == "" } {
609       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{ffmpeg}*] "$::VCVER" "$anArchIter" ]
610       set aFFmpegLibPath [wokdep:SearchLib "avutil" "$anArchIter" "$aPath/lib"]
611       if { "$aFFmpegLibPath" != "" } {
612         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
613         lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
614       } else {
615         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}avutil.${::SYS_LIB_SUFFIX}' not found (FFmpeg)"
616         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
617       }
618     }
619   }
620
621   return "$isFound"
622 }
623
624 # Search TBB library placement
625 proc wokdep:SearchTBB {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
626   upvar $theErrInc   anErrInc
627   upvar $theErrLib32 anErrLib32
628   upvar $theErrLib64 anErrLib64
629   upvar $theErrBin32 anErrBin32
630   upvar $theErrBin64 anErrBin64
631
632   # keep only two first digits in "vc141"
633   if { ! [regexp {^vc[0-9][0-9]} ${::VCVER} aVcLib] } {
634     set aVcLib ${::VCVER}
635   }
636
637   set isFound "true"
638   set aTbbHPath [wokdep:SearchHeader "tbb/scalable_allocator.h"]
639   if { "$aTbbHPath"  == "" } {
640     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{tbb}*] "$::VCVER" "$::ARCH" ]
641     if { "$aPath" != "" && [file exists "$aPath/include/tbb/scalable_allocator.h"] } {
642       lappend ::CSF_OPT_INC "$aPath/include"
643     } else {
644       lappend anErrInc "Error: 'tbb/scalable_allocator.h' not found (Intel TBB)"
645       set isFound "false"
646     }
647   }
648
649   foreach anArchIter {64 32} {
650     set aSubDir "ia32"
651     if { "$anArchIter" == "64"} {
652       set aSubDir "intel64"
653     }
654
655     set aTbbLibPath [wokdep:SearchLib "tbb" "$anArchIter"]
656     if { "$aTbbLibPath" == "" } {
657       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{tbb}*] $aVcLib "$anArchIter" ]
658       set aTbbLibPath [wokdep:SearchLib "tbb" "$anArchIter" "$aPath/lib/$aSubDir/$aVcLib"]
659       if { "$aTbbLibPath" == "" } {
660         # Set the path to the TBB library for Linux
661         if { "$::tcl_platform(platform)" != "windows" } {
662           set aSubDir "$aSubDir/cc4.1.0_libc2.4_kernel2.6.16.21"
663         }
664         set aTbbLibPath [wokdep:SearchLib "tbb" "$anArchIter" "$aPath/lib/$aSubDir"]
665         if { "$aTbbLibPath" != "" } {
666           lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib/$aSubDir"
667         }
668       } else {
669         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib/$aSubDir/$aVcLib"
670       }
671       if { "$aTbbLibPath" == "" } {
672         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}tbb.${::SYS_LIB_SUFFIX}' not found (Intel TBB)"
673         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
674       }
675     }
676     if { "$::tcl_platform(platform)" == "windows" } {
677       set aTbbDllPath [wokdep:SearchBin "tbb.dll" "$anArchIter"]
678       if { "$aTbbDllPath" == "" } {
679         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{tbb}*] $aVcLib "$anArchIter" ]
680         set aTbbDllPath [wokdep:SearchBin "tbb.dll" "$anArchIter" "$aPath/bin/$aSubDir/$aVcLib"]
681         if { "$aTbbDllPath" != "" } {
682           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin/$aSubDir/$aVcLib"
683         } else {
684           lappend anErrBin$anArchIter "Error: 'tbb.dll' not found (Intel TBB)"
685           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
686         }
687       }
688     }
689   }
690
691   return "$isFound"
692 }
693
694 # Search OpenCL library placement
695 proc wokdep:SearchOpenCL {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
696   upvar $theErrInc   anErrInc
697   upvar $theErrLib32 anErrLib32
698   upvar $theErrLib64 anErrLib64
699   upvar $theErrBin32 anErrBin32
700   upvar $theErrBin64 anErrBin64
701
702   set isFound "true"
703   if { "$::tcl_platform(os)" == "Darwin" } {
704     # OpenCL framework available since Mac OS X 16
705     return "$isFound"
706   }
707
708   set aCLHPath [wokdep:SearchHeader "CL/cl_gl.h"]
709   if { "$aCLHPath"  == "" } {
710     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{OpenCL}*] "$::VCVER" "$::ARCH" ]
711     if { "$aPath" != "" && [file exists "$aPath/include/CL/cl_gl.h"] } {
712       lappend ::CSF_OPT_INC "$aPath/include"
713     } else {
714       lappend anErrInc "Error: 'CL/cl_gl.h' not found (OpenCL)"
715       set isFound "false"
716     }
717   }
718
719   foreach anArchIter {64 32} {
720     set aCLLibPath [wokdep:SearchLib "OpenCL" "$anArchIter"]
721     if { "$aCLLibPath" == "" } {
722       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{OpenCL}*] "$::VCVER" "$anArchIter" ]
723       set aCLLibPath [wokdep:SearchLib "OpenCL" "$anArchIter" "$aPath/lib"]
724       if { "$aCLLibPath" != "" } {
725         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
726       } else {
727         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}OpenCL.${::SYS_LIB_SUFFIX}' not found (OpenCL)"
728         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
729       }
730     }
731   }
732
733   return "$isFound"
734 }
735
736 # Search EGL library placement
737 proc wokdep:SearchEGL {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
738   upvar $theErrInc   anErrInc
739   upvar $theErrLib32 anErrLib32
740   upvar $theErrLib64 anErrLib64
741   upvar $theErrBin32 anErrBin32
742   upvar $theErrBin64 anErrBin64
743
744   set isFound "true"
745   set aHeaderPath [wokdep:SearchHeader "EGL/egl.h"]
746   if { "$aHeaderPath"  == "" } {
747     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{EGL}*] "$::VCVER" "$::ARCH" ]
748     if { "$aPath" == "" || ![file exists "$aPath/include/EGL/egl.h"] } {
749       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{angle}*] "$::VCVER" "$::ARCH" ]
750     }
751
752     if { "$aPath" != "" && [file exists "$aPath/include/EGL/egl.h"] } {
753       lappend ::CSF_OPT_INC "$aPath/include"
754     } else {
755       lappend anErrInc "Error: 'EGL/egl.h' not found (EGL)"
756       set isFound "false"
757     }
758   }
759
760   set aLibName "EGL"
761   if { "$::tcl_platform(platform)" == "windows" } {
762     # awkward exception
763     set aLibName "libEGL"
764   }
765
766   foreach anArchIter {64 32} {
767     set aLibPath [wokdep:SearchLib "$aLibName" "$anArchIter"]
768     if { "$aLibPath" == "" } {
769       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{EGL}*] "$::VCVER" "$anArchIter" ]
770       set aLibPath [wokdep:SearchLib "$aLibName" "$anArchIter" "$aPath/lib"]
771       if { "$aLibPath" == "" } {
772         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{angle}*] "$::VCVER" "$anArchIter" ]
773         set aLibPath [wokdep:SearchLib "$aLibName" "$anArchIter" "$aPath/lib"]
774       }
775
776       if { "$aLibPath" != "" } {
777         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
778       } else {
779         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}${aLibName}.${::SYS_LIB_SUFFIX}' not found (EGL)"
780         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
781       }
782     }
783
784     if { "$::tcl_platform(platform)" == "windows" } {
785       set aDllPath [wokdep:SearchBin "libEGL.dll" "$anArchIter"]
786       if { "$aDllPath" == "" } {
787         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{EGL}*] "$::VCVER" "$anArchIter" ]
788         set aDllPath [wokdep:SearchBin "libEGL.dll" "$anArchIter" "$aPath/bin"]
789         if { "$aDllPath" == "" } {
790           set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{angle}*] "$::VCVER" "$anArchIter" ]
791           set aDllPath [wokdep:SearchBin "libEGL.dll" "$anArchIter" "$aPath/bin"]
792         }
793
794         if { "$aDllPath" != "" } {
795           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
796         } else {
797           lappend anErrBin$anArchIter "Error: 'libEGL.dll' not found (EGL)"
798           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
799         }
800       }
801     }
802   }
803
804   return "$isFound"
805 }
806
807 # Search OpenGL ES 2.0 library placement
808 proc wokdep:SearchGLES {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
809   upvar $theErrInc   anErrInc
810   upvar $theErrLib32 anErrLib32
811   upvar $theErrLib64 anErrLib64
812   upvar $theErrBin32 anErrBin32
813   upvar $theErrBin64 anErrBin64
814
815   set isFound "true"
816   set aHeaderPath [wokdep:SearchHeader "GLES2/gl2.h"]
817   if { "$aHeaderPath"  == "" } {
818     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{GLES}*] "$::VCVER" "$::ARCH" ]
819     if { "$aPath" == "" || ![file exists "$aPath/include/GLES2/gl2.h"] } {
820       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{angle}*] "$::VCVER" "$::ARCH" ]
821     }
822
823     if { "$aPath" != "" && [file exists "$aPath/include/GLES2/gl2.h"] } {
824       lappend ::CSF_OPT_INC "$aPath/include"
825     } else {
826       lappend anErrInc "Error: 'GLES2/gl2.h' not found (OpenGL ES 2.0)"
827       set isFound "false"
828     }
829   }
830
831   set aLibName "GLESv2"
832   if { "$::tcl_platform(platform)" == "windows" } {
833     # awkward exception
834     set aLibName "libGLESv2"
835   }
836
837   foreach anArchIter {64 32} {
838     set aLibPath [wokdep:SearchLib "$aLibName" "$anArchIter"]
839     if { "$aLibPath" == "" } {
840       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{GLES}*] "$::VCVER" "$anArchIter" ]
841       set aLibPath [wokdep:SearchLib "$aLibName" "$anArchIter" "$aPath/lib"]
842       if { "$aLibPath" == "" } {
843         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{angle}*] "$::VCVER" "$anArchIter" ]
844         set aLibPath [wokdep:SearchLib "$aLibName" "$anArchIter" "$aPath/lib"]
845       }
846
847       if { "$aLibPath" != "" } {
848         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
849       } else {
850         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}${aLibName}.${::SYS_LIB_SUFFIX}' not found (OpenGL ES 2.0)"
851         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
852       }
853     }
854
855     if { "$::tcl_platform(platform)" == "windows" } {
856       set aDllPath [wokdep:SearchBin "libGLESv2.dll" "$anArchIter"]
857       if { "$aDllPath" == "" } {
858         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{EGL}*] "$::VCVER" "$anArchIter" ]
859         set aDllPath [wokdep:SearchBin "libGLESv2.dll" "$anArchIter" "$aPath/bin"]
860         if { "$aDllPath" == "" } {
861           set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{angle}*] "$::VCVER" "$anArchIter" ]
862           set aDllPath [wokdep:SearchBin "libGLESv2.dll" "$anArchIter" "$aPath/bin"]
863         }
864
865         if { "$aDllPath" != "" } {
866           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
867         } else {
868           lappend anErrBin$anArchIter "Error: 'libGLESv2.dll' not found (OpenGL ES 2.0)"
869           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
870         }
871       }
872     }
873   }
874
875   return "$isFound"
876 }
877
878 # Search RapidJSON headers
879 proc wokdep:SearchRapidJson {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
880   upvar $theErrInc anErrInc
881
882   set isFound "true"
883   set aRJHPath [wokdep:SearchHeader "rapidjson/rapidjson.h"]
884   if { "$aRJHPath"  == "" } {
885     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{rapidjson}*] "$::VCVER" "$::ARCH" ]
886     if { "$aPath" != "" && [file exists "$aPath/include/rapidjson/rapidjson.h"] } {
887       lappend ::CSF_OPT_INC "$aPath/include"
888     } else {
889       lappend anErrInc "Error: 'rapidjson/rapidjson.h' not found (RapidJSON)"
890       set isFound "false"
891     }
892   }
893
894   return "$isFound"
895 }
896
897 # Auxiliary function, gets VTK version to set default search directory
898 proc wokdep:VtkVersion { thePath } {
899   set aResult "6.1"
900
901   set aVtkRoot [lindex [regexp -all -inline {[0-9.]*} [file tail $thePath]] 0]
902   if { "$aVtkRoot" != "" } {
903     set aVtkRoot [regexp -inline {[0-9]*.[0-9]*} $aVtkRoot]
904     if { "$aVtkRoot" != "" } {
905     set aResult $aVtkRoot
906     }
907   }
908
909   return $aResult
910 }
911
912 # Search VTK library placement
913 proc wokdep:SearchVTK {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
914   upvar $theErrInc   anErrInc
915   upvar $theErrLib32 anErrLib32
916   upvar $theErrLib64 anErrLib64
917   upvar $theErrBin32 anErrBin32
918   upvar $theErrBin64 anErrBin64
919
920   set isFound "true"
921   
922   set aVtkPath ""
923   set aVtkIncPath [wokdep:SearchHeader "vtkConfigure.h"]
924   set aVtkVer [wokdep:VtkVersion $aVtkIncPath]
925   if { "$aVtkIncPath" == ""} {
926     set aPathList [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{VTK}*]
927     set aVtkPath [wokdep:Preferred "$aPathList" "$::VCVER" "$::ARCH" ]
928     if { "$aVtkPath" != "" && [file exists "$aVtkPath/include/vtk-[wokdep:VtkVersion $aVtkPath]/vtkConfigure.h"]} { 
929       set aVtkVer [wokdep:VtkVersion $aVtkPath]
930       lappend ::CSF_OPT_INC "$aVtkPath/include/vtk-[wokdep:VtkVersion $aVtkPath]"
931     } else { # try to search in all found paths
932       set isFound "false"
933       foreach anIt $aPathList {
934         if { [file exists "$anIt/include/vtk-[wokdep:VtkVersion $anIt]/vtkConfigure.h"] } {
935           set aVtkPath $anIt
936           set aVtkVer [wokdep:VtkVersion $aVtkPath]
937           lappend ::CSF_OPT_INC "$anIt/include/vtk-[wokdep:VtkVersion $anIt]"
938           set isFound "true"
939           break
940         }
941       }
942
943       # Bad case: we do not found vtkConfigure.h in all paths.
944       if { "$isFound" == "false"} {
945         lappend anErrInc "Error: 'vtkConfigure.h' not found (VTK)"
946         set isFound "false"
947       }
948     }
949   }
950
951   set aVtkLibPath ""
952   foreach anArchIter {64 32} {
953     set aVtkLibPath [wokdep:SearchLib "vtkCommonCore-$aVtkVer" "$anArchIter"]
954     if { "$aVtkLibPath" == "" } {
955       set aPathList [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{VTK}*]
956       set aPath [wokdep:Preferred $aPathList "$::VCVER" "$anArchIter" ]
957       set aVtkLibPath [wokdep:SearchLib "vtkCommonCore-$aVtkVer" "$anArchIter" "$aPath/lib"]
958       if { "$aVtkLibPath" != "" } {
959         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
960       } else {
961         set aPath [wokdep:SearchLib "vtkCommonCore-$aVtkVer" "$anArchIter" "$aVtkPath/lib"]
962         if { "$aPath" != "" } {
963           set aLibPath $aVtkIncPath
964           lappend ::CSF_OPT_LIB$anArchIter "$aLibPath/lib"
965         } else {
966           # The last chance: search /lib directory in all found paths
967           foreach anIt $aPathList {
968             set aVtkLibPath [wokdep:SearchLib "vtkCommonCore-$aVtkVer" "$anArchIter" "$anIt/lib"]
969             if { "$aVtkLibPath" != ""} {
970               lappend ::CSF_OPT_LIB$anArchIter "$anIt/lib"
971               break
972             }
973           }
974           if { "$aVtkLibPath" == "" } {
975             lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}vtkCommonCore-${aVtkVer}\.${::SYS_LIB_SUFFIX}' not found (VTK)"
976             if { "$::ARCH" == "$anArchIter" } {
977               set isFound "false"
978             }
979           }
980         }
981       }
982     }
983   }
984   
985     # Search binary path
986     if { "$::tcl_platform(platform)" == "windows" } {
987       foreach anArchIter {64 32} {
988         set aVtkBinPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter"]
989         if { "$aVtkBinPath" == "" } {
990           set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{VTK}*] "$::VCVER" "$anArchIter" ]
991           set aVtkBinPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aPath/bin"]
992           if { "$aVtkBinPath" != "" } { lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
993           } else {
994             set aVtkBinPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aPath/lib"]
995             if { "$aVtkBinPath" != "" } { lappend ::CSF_OPT_BIN$anArchIter "$aPath/lib" } 
996           }
997         }
998       }
999       
1000       # We didn't find preferred binary path => search through inc path or among all available VTK directories
1001       if { "$aVtkBinPath" == "" } {
1002         # Try to find in lib path
1003         set aPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aVtkLibPath/bin"]
1004         if { "$aPath" != "" } { lappend ::CSF_OPT_BIN$anArchIter "$aVtkLibPath/bin"
1005         } elseif { [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aVtkLibPath/lib"] != "" } {
1006           lappend ::CSF_OPT_BIN$anArchIter "$aVtkLibPath/lib"
1007         } else {
1008            lappend anErrBin$anArchIter "Error: 'vtkCommonCore-${aVtkVer}.dll' not found (VTK)"
1009            set isFound "false"
1010         }
1011       }
1012     }
1013
1014   return "$isFound"
1015 }
1016
1017 # Search Qt4 libraries placement
1018 proc wokdep:SearchQt4 {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
1019   upvar $theErrInc   anErrInc
1020   upvar $theErrLib32 anErrLib32
1021   upvar $theErrLib64 anErrLib64
1022   upvar $theErrBin32 anErrBin32
1023   upvar $theErrBin64 anErrBin64
1024
1025   set isFound "true"
1026   set aQMsgBoxHPath [wokdep:SearchHeader "QtGui/qmessagebox.h"]
1027   if { "$aQMsgBoxHPath" == "" } {
1028     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{qt4}*] "$::VCVER" "$::ARCH" ]
1029     if { "$aPath" != "" && [file exists "$aPath/include/QtGui/qmessagebox.h"] } {
1030       lappend ::CSF_OPT_INC "$aPath/include"
1031       lappend ::CSF_OPT_INC "$aPath/include/Qt"
1032       lappend ::CSF_OPT_INC "$aPath/include/QtGui"
1033       lappend ::CSF_OPT_INC "$aPath/include/QtCore"
1034     } else {
1035       if { [file exists "/usr/include/qt4/QtGui/qmessagebox.h"] } {
1036         lappend ::CSF_OPT_INC "/usr/include/qt4"
1037         lappend ::CSF_OPT_INC "/usr/include/qt4/Qt"
1038         lappend ::CSF_OPT_INC "/usr/include/qt4/QtGui"
1039         lappend ::CSF_OPT_INC "/usr/include/qt4/QtCore"
1040       } else {
1041         lappend anErrInc "Error: 'QtGui/qmessagebox.h' not found (Qt4)"
1042         set isFound "false"
1043       }
1044     }
1045   }
1046
1047   set aQtGuiLibName "QtGui"
1048   if { "$::tcl_platform(platform)" == "windows" } {
1049     set aQtGuiLibName "QtGui4"
1050   }
1051
1052   foreach anArchIter {64 32} {
1053     set aQMsgBoxLibPath [wokdep:SearchLib "${aQtGuiLibName}" "$anArchIter"]
1054     if { "$aQMsgBoxLibPath" == "" } {
1055       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{qt4}*] "$::VCVER" "$anArchIter" ]
1056       set aQMsgBoxLibPath [wokdep:SearchLib "${aQtGuiLibName}" "$anArchIter" "$aPath/lib"]
1057       if { "$aQMsgBoxLibPath" != "" } {
1058         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
1059       } else {
1060         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}${aQtGuiLibName}.${::SYS_LIB_SUFFIX}' not found (Qt4)"
1061         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
1062       }
1063     }
1064     if { "$::tcl_platform(platform)" == "windows" } {
1065       set aQMsgBoxDllPath [wokdep:SearchBin "QtGui4.dll" "$anArchIter"]
1066       if { "$aQMsgBoxDllPath" == "" } {
1067         set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{qt4}*] "$::VCVER" "$anArchIter" ]
1068         set aQMsgBoxDllPath [wokdep:SearchBin "QtGui4.dll" "$anArchIter" "$aPath/bin"]
1069         if { "$aQMsgBoxDllPath" != "" } {
1070           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
1071         } else {
1072           lappend anErrBin$anArchIter "Error: 'QtGui4.dll' not found (Qt4)"
1073           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
1074         }
1075       }
1076     }
1077   }
1078
1079   return "$isFound"
1080 }
1081
1082 # Search JDK placement
1083 proc wokdep:SearchJDK {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
1084   upvar $theErrInc   anErrInc
1085   upvar $theErrLib32 anErrLib32
1086   upvar $theErrLib64 anErrLib64
1087   upvar $theErrBin32 anErrBin32
1088   upvar $theErrBin64 anErrBin64
1089
1090   set isFound "true"
1091   set aJniHPath   [wokdep:SearchHeader "jni.h"]
1092   set aJniMdHPath [wokdep:SearchHeader "jni_md.h"]
1093   if { "$aJniHPath" == "" || "$aJniMdHPath" == "" } {
1094     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{jdk,java}*] "$::VCVER" "$::ARCH" ]
1095     if { "$aPath" != "" && [file exists "$aPath/include/jni.h"] } {
1096       lappend ::CSF_OPT_INC "$aPath/include"
1097       if { "$::tcl_platform(platform)" == "windows" } {
1098         lappend ::CSF_OPT_INC "$aPath/include/win32"
1099       } elseif { [file exists "$aPath/include/linux"] } {
1100         lappend ::CSF_OPT_INC "$aPath/include/linux"
1101       }
1102     } else {
1103       if { [file exists "/System/Library/Frameworks/JavaVM.framework/Home/include/jni.h"] } {
1104         lappend ::CSF_OPT_INC "/System/Library/Frameworks/JavaVM.framework/Home/include"
1105       } else {
1106         lappend anErrInc "Error: 'jni.h' or 'jni_md.h' not found (JDK)"
1107         set isFound "false"
1108       }
1109     }
1110   }
1111
1112   foreach anArchIter {64 32} {
1113     set aJavacPath [wokdep:SearchBin "javac${::SYS_EXE_SUFFIX}" "$anArchIter"]
1114     if { "$aJavacPath" == "" } {
1115       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{jdk,java}*] "$::VCVER" "$anArchIter" ]
1116       set aJavacPath [wokdep:SearchBin "javac${::SYS_EXE_SUFFIX}" "$anArchIter" "$aPath/bin"]
1117       if { "$aJavacPath" != "" } {
1118         lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
1119       } else {
1120         if { "$::ARCH" == "$anArchIter" && [file exists "/System/Library/Frameworks/JavaVM.framework/Home/bin/javac${::SYS_EXE_SUFFIX}"] } {
1121           lappend ::CSF_OPT_BIN$anArchIter "/System/Library/Frameworks/JavaVM.framework/Home/bin"
1122         } else {
1123           lappend anErrBin$anArchIter "Error: 'javac${::SYS_EXE_SUFFIX}' not found (JDK)"
1124           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
1125         }
1126       }
1127     }
1128   }
1129
1130   return "$isFound"
1131 }
1132
1133 # Search X11 libraries placement
1134 proc wokdep:SearchX11 {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
1135   upvar $theErrInc   anErrInc
1136   upvar $theErrLib32 anErrLib32
1137   upvar $theErrLib64 anErrLib64
1138   upvar $theErrBin32 anErrBin32
1139   upvar $theErrBin64 anErrBin64
1140
1141   set isFound "true"
1142   if { "$::tcl_platform(platform)" == "windows" || ( "$::tcl_platform(os)" == "Darwin" && "$::MACOSX_USE_GLX" != "true" ) } {
1143     return "$isFound"
1144   }
1145
1146   set aXmuLibPath [wokdep:SearchLib "Xmu" "$::ARCH"]
1147   if { "$aXmuLibPath" == "" } {
1148     set aXmuLibPath [wokdep:SearchLib "Xmu" "$::ARCH" "/usr/X11/lib"]
1149     if { "$aXmuLibPath" != "" } {
1150       #lappend ::CSF_OPT_LIB$::ARCH "/usr/X11/lib"
1151     } else {
1152       lappend anErrLib$::ARCH "Error: '${::SYS_LIB_PREFIX}Xmu.${::SYS_LIB_SUFFIX}' not found (X11)"
1153       set isFound "false"
1154     }
1155   }
1156
1157   return "$isFound"
1158 }
1159
1160 # Returns OCCT version string from file Standard_Version.hxx (if available)
1161 proc wokdep:DetectCasVersion {} {
1162   set occt_ver 7.0.0
1163   set aCasRoot [file normalize [file dirname [info script]]]
1164   set filename "${aCasRoot}/src/Standard/Standard_Version.hxx"
1165   if { [file exists $filename] } {
1166     set fh [open $filename "r"]
1167     set fh_loaded [read $fh]
1168     close $fh
1169     regexp {[^/]\s*#\s*define\s+OCC_VERSION_COMPLETE\s+\"([^\s]*)\"} $fh_loaded dummy occt_ver
1170   } else {
1171     puts "Error: file '$filename' not found"
1172   }
1173   return $occt_ver
1174 }
1175
1176 # Generate (override) custom environment file
1177 proc wokdep:SaveCustom {} {
1178   set aGenInfo "This environment file was generated by genconf.tcl script at [clock format [clock seconds] -format "%Y.%m.%d %H:%M"]"
1179   if { "$::tcl_platform(platform)" == "windows" } {
1180     set aCustomFilePath "./custom.bat"
1181     set aFile [open $aCustomFilePath "w"]
1182     puts $aFile "@echo off"
1183     puts $aFile "rem $aGenInfo"
1184
1185     puts $aFile ""
1186     puts $aFile "set PRJFMT=$::PRJFMT"
1187     puts $aFile "set VCVER=$::VCVER"
1188     puts $aFile "set ARCH=$::ARCH"
1189     puts $aFile "set VCVARS=$::VCVARS"
1190     puts $aFile "set SHORTCUT_HEADERS=$::SHORTCUT_HEADERS"
1191
1192     puts $aFile ""
1193     puts $aFile "set \"PRODUCTS_PATH=$::PRODUCTS_PATH\""
1194
1195     puts $aFile ""
1196     puts $aFile "rem Optional 3rd-parties switches"
1197     foreach anEnvIter $::THE_ENV_VARIABLES {
1198       set aName ${anEnvIter}
1199       set aValue [set ::${anEnvIter}]
1200       if { "$aValue" != "" } {
1201         puts $aFile "set ${aName}=$aValue"
1202       }
1203     }
1204
1205     set aStringInc [join $::CSF_OPT_INC $::SYS_PATH_SPLITTER]
1206     if { "$::PRODUCTS_PATH" != "" } {
1207       set aStringInc [regsub -all "$::PRODUCTS_PATH" $aStringInc "%PRODUCTS_PATH%"]
1208     }
1209     puts $aFile ""
1210     puts $aFile "rem Additional headers search paths"
1211     puts $aFile "set \"CSF_OPT_INC=$aStringInc\""
1212
1213     set aStringLib32 [join $::CSF_OPT_LIB32 $::SYS_PATH_SPLITTER]
1214     if { "$::PRODUCTS_PATH" != "" } {
1215       set aStringLib32 [regsub -all "$::PRODUCTS_PATH" $aStringLib32 "%PRODUCTS_PATH%"]
1216     }
1217     puts $aFile ""
1218     puts $aFile "rem Additional libraries (32-bit) search paths"
1219     puts $aFile "set \"CSF_OPT_LIB32=$aStringLib32\""
1220
1221     set aStringLib64 [join $::CSF_OPT_LIB64 $::SYS_PATH_SPLITTER]
1222     if { "$::PRODUCTS_PATH" != "" } {
1223       set aStringLib64 [regsub -all "$::PRODUCTS_PATH" $aStringLib64 "%PRODUCTS_PATH%"]
1224     }
1225     puts $aFile ""
1226     puts $aFile "rem Additional libraries (64-bit) search paths"
1227     puts $aFile "set \"CSF_OPT_LIB64=$aStringLib64\""
1228
1229     set aStringBin32 [join $::CSF_OPT_BIN32 $::SYS_PATH_SPLITTER]
1230     if { "$::PRODUCTS_PATH" != "" } {
1231       set aStringBin32 [regsub -all "$::PRODUCTS_PATH" $aStringBin32 "%PRODUCTS_PATH%"]
1232     }
1233     puts $aFile ""
1234     puts $aFile "rem Additional (32-bit) search paths"
1235     puts $aFile "set \"CSF_OPT_BIN32=$aStringBin32\""
1236
1237     set aStringBin64 [join $::CSF_OPT_BIN64 $::SYS_PATH_SPLITTER]
1238     if { "$::PRODUCTS_PATH" != "" } {
1239       set aStringBin64 [regsub -all "$::PRODUCTS_PATH" $aStringBin64 "%PRODUCTS_PATH%"]
1240     }
1241     puts $aFile ""
1242     puts $aFile "rem Additional (64-bit) search paths"
1243     puts $aFile "set \"CSF_OPT_BIN64=$aStringBin64\""
1244
1245     close $aFile
1246   } else {
1247     set aCustomFilePath "./custom.sh"
1248     set aFile [open $aCustomFilePath "w"]
1249     puts $aFile "#!/bin/bash"
1250     puts $aFile "# $aGenInfo"
1251
1252     puts $aFile ""
1253     puts $aFile "export PRJFMT=$::PRJFMT"
1254     puts $aFile "export ARCH=$::ARCH"
1255     puts $aFile "export SHORTCUT_HEADERS=$::SHORTCUT_HEADERS"
1256
1257     puts $aFile ""
1258     puts $aFile "export PRODUCTS_PATH=\"$::PRODUCTS_PATH\""
1259
1260     puts $aFile ""
1261     puts $aFile "# Optional 3rd-parties switches"
1262     foreach anEnvIter $::THE_ENV_VARIABLES {
1263       set aName ${anEnvIter}
1264       set aValue [set ::${anEnvIter}]
1265       if { "$aValue" != "" } {
1266         puts $aFile "export ${aName}=${aValue}"
1267       }
1268     }
1269
1270     set aStringInc [join $::CSF_OPT_INC $::SYS_PATH_SPLITTER]
1271     if { "$::PRODUCTS_PATH" != "" } {
1272       set aStringInc [regsub -all "$::PRODUCTS_PATH" $aStringInc "\${PRODUCTS_PATH}"]
1273     }
1274     puts $aFile ""
1275     puts $aFile "# Additional headers search paths"
1276     puts $aFile "export CSF_OPT_INC=\"$aStringInc\""
1277
1278     set aStringLib [join [set ::CSF_OPT_LIB$::ARCH] $::SYS_PATH_SPLITTER]
1279     if { "$::PRODUCTS_PATH" != "" } {
1280       set aStringLib [regsub -all "$::PRODUCTS_PATH" $aStringLib "\${PRODUCTS_PATH}"]
1281     }
1282     puts $aFile ""
1283     puts $aFile "# Additional libraries ($::ARCH-bit) search paths"
1284     puts $aFile "export CSF_OPT_LIB$::ARCH=\"[set aStringLib]\""
1285
1286     set aStringBin [join [set ::CSF_OPT_BIN$::ARCH] $::SYS_PATH_SPLITTER]
1287     if { "$::PRODUCTS_PATH" != "" } {
1288       set aStringBin [regsub -all "$::PRODUCTS_PATH" $aStringBin "\${PRODUCTS_PATH}"]
1289     }
1290     puts $aFile ""
1291     puts $aFile "# Additional ($::ARCH-bit) search paths"
1292     puts $aFile "export CSF_OPT_BIN$::ARCH=\"[set aStringBin]\""
1293
1294     close $aFile
1295   }
1296   puts "Configuration saved to file '$aCustomFilePath'"
1297
1298   # generate custom.auto.pri
1299   set toExportCustomPri 1
1300   if { $toExportCustomPri == 1 } {
1301     set aCasVer [wokdep:DetectCasVersion]
1302     set aCustomFilePath "./adm/qmake/custom.auto.pri"
1303     set aFile [open $aCustomFilePath "w"]
1304     puts $aFile "# $aGenInfo"
1305
1306     puts $aFile ""
1307     puts $aFile "VERSION=$aCasVer"
1308     puts $aFile "PRODUCTS_PATH=\"$::PRODUCTS_PATH\""
1309
1310     puts $aFile ""
1311     puts $aFile "# Optional 3rd-parties switches"
1312     foreach anEnvIter $::THE_ENV_VARIABLES {
1313       set aName ${anEnvIter}
1314       set aValue [set ::${anEnvIter}]
1315       if { "$aValue" == "true" } {
1316         puts $aFile "CONFIG += ${aName}"
1317       } else {
1318         #puts $aFile "CONFIG -= ${aName}"
1319       }
1320     }
1321
1322     puts $aFile ""
1323     puts $aFile "# Additional headers search paths"
1324     foreach anIncPath $::CSF_OPT_INC {
1325       if { "$::PRODUCTS_PATH" != "" } {
1326         set anIncPath [regsub -all "$::PRODUCTS_PATH" $anIncPath "\$\$\{PRODUCTS_PATH\}"]
1327       }
1328       puts $aFile "INCLUDEPATH += \"${anIncPath}\""
1329     }
1330
1331     puts $aFile ""
1332     puts $aFile "# Additional libraries search paths"
1333     foreach aLibPath [set ::CSF_OPT_LIB$::ARCH] {
1334       if { "$::PRODUCTS_PATH" != "" } {
1335         set aLibPath [regsub -all "$::PRODUCTS_PATH" $aLibPath "\$\$\{PRODUCTS_PATH\}"]
1336       }
1337       puts $aFile "LIBS += -L\"${aLibPath}\""
1338     }
1339
1340     if { "$::tcl_platform(platform)" == "windows" } {
1341       puts $aFile ""
1342       puts $aFile "# Additional DLLs search paths"
1343       foreach aDllPath [set ::CSF_OPT_BIN$::ARCH] {
1344         if { "$::PRODUCTS_PATH" != "" } {
1345           set aDllPath [regsub -all "$::PRODUCTS_PATH" $aDllPath "\$\$\{PRODUCTS_PATH\}"]
1346         }
1347         puts $aFile "LIBS += -L\"${aDllPath}\""
1348       }
1349     }
1350
1351     puts $aFile ""
1352     close $aFile
1353     puts "Configuration saved to file '$aCustomFilePath'"
1354   }
1355 }