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