0032308: Configuration - make Xlib dependency optional
[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   
1049     # Search binary path
1050     if { "$::tcl_platform(platform)" == "windows" } {
1051       foreach anArchIter {64 32} {
1052         set aVtkBinPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter"]
1053         if { "$aVtkBinPath" == "" } {
1054           set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{VTK}*] "$::VCVER" "$anArchIter" ]
1055           set aVtkBinPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aPath/bin"]
1056           if { "$aVtkBinPath" != "" } { lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
1057           } else {
1058             set aVtkBinPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aPath/lib"]
1059             if { "$aVtkBinPath" != "" } { lappend ::CSF_OPT_BIN$anArchIter "$aPath/lib" } 
1060           }
1061         }
1062       }
1063       
1064       # We didn't find preferred binary path => search through inc path or among all available VTK directories
1065       if { "$aVtkBinPath" == "" } {
1066         # Try to find in lib path
1067         set aPath [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aVtkLibPath/bin"]
1068         if { "$aPath" != "" } { lappend ::CSF_OPT_BIN$anArchIter "$aVtkLibPath/bin"
1069         } elseif { [wokdep:SearchBin "vtkCommonCore-${aVtkVer}.dll" "$anArchIter" "$aVtkLibPath/lib"] != "" } {
1070           lappend ::CSF_OPT_BIN$anArchIter "$aVtkLibPath/lib"
1071         } else {
1072            lappend anErrBin$anArchIter "Error: 'vtkCommonCore-${aVtkVer}.dll' not found (VTK)"
1073            set isFound "false"
1074         }
1075       }
1076     }
1077
1078   return "$isFound"
1079 }
1080
1081 # Search Qt libraries placement
1082 proc wokdep:SearchQt {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
1083   upvar $theErrInc   anErrInc
1084   upvar $theErrLib32 anErrLib32
1085   upvar $theErrLib64 anErrLib64
1086   upvar $theErrBin32 anErrBin32
1087   upvar $theErrBin64 anErrBin64
1088
1089   set isFound "true"
1090   set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{qt}*] "$::VCVER" "$::ARCH" ] 
1091   set aQMsgBoxHPath [wokdep:SearchHeader "QtGui/qguiapplication.h"]
1092   if { "$aQMsgBoxHPath" == "" } {
1093     if { "$aPath" != "" && [file exists "$aPath/include/QtGui/qguiapplication.h"] } {
1094       lappend ::CSF_OPT_INC "$aPath/include"
1095       lappend ::CSF_OPT_INC "$aPath/include/Qt"
1096       lappend ::CSF_OPT_INC "$aPath/include/QtGui"
1097       lappend ::CSF_OPT_INC "$aPath/include/QtCore"
1098       lappend ::CSF_OPT_INC "$aPath/include/QtWidgets"
1099       lappend ::CSF_OPT_INC "$aPath/include/QtXml"
1100     } else {
1101       lappend anErrInc "Error: 'QtGui/qguiapplication.h' not found"
1102         set isFound "false"
1103     }
1104   }
1105
1106   set aQtGuiLibName "QtGui"
1107   if { "$::tcl_platform(platform)" == "windows" } {
1108     set aQtGuiLibName "Qt5Gui"
1109   }
1110
1111   foreach anArchIter {64 32} {
1112     set aQMsgBoxLibPath [wokdep:SearchLib "${aQtGuiLibName}" "$anArchIter"]
1113     if { "$aQMsgBoxLibPath" == "" } {
1114       set aQMsgBoxLibPath [wokdep:SearchLib "${aQtGuiLibName}" "$anArchIter" "$aPath/lib"]
1115       if { "$aQMsgBoxLibPath" != "" } {
1116         lappend ::CSF_OPT_LIB$anArchIter "$aPath/lib"
1117       } else {
1118         lappend anErrLib$anArchIter "Error: '${::SYS_LIB_PREFIX}${aQtGuiLibName}.${::SYS_LIB_SUFFIX}' not found (Qt)"
1119         if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
1120       }
1121     }
1122     if { "$::tcl_platform(platform)" == "windows" } {
1123       set aQMsgBoxDllPath [wokdep:SearchBin "${aQtGuiLibName}.dll" "$anArchIter"]
1124       if { "$aQMsgBoxDllPath" == "" } {
1125         set aQMsgBoxDllPath [wokdep:SearchBin "${aQtGuiLibName}.dll" "$anArchIter" "$aPath/bin"]
1126         if { "$aQMsgBoxDllPath" != "" } {
1127           lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
1128         } else {
1129           lappend anErrBin$anArchIter "Error: '${aQtGuiLibName}.dll' not found (Qt)"
1130           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
1131         }
1132       }
1133     }
1134   }
1135
1136   return "$isFound"
1137 }
1138
1139 # Search JDK placement
1140 proc wokdep:SearchJDK {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
1141   upvar $theErrInc   anErrInc
1142   upvar $theErrLib32 anErrLib32
1143   upvar $theErrLib64 anErrLib64
1144   upvar $theErrBin32 anErrBin32
1145   upvar $theErrBin64 anErrBin64
1146
1147   set isFound "true"
1148   set aJniHPath   [wokdep:SearchHeader "jni.h"]
1149   set aJniMdHPath [wokdep:SearchHeader "jni_md.h"]
1150   if { "$aJniHPath" == "" || "$aJniMdHPath" == "" } {
1151     set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{jdk,java}*] "$::VCVER" "$::ARCH" ]
1152     if { "$aPath" != "" && [file exists "$aPath/include/jni.h"] } {
1153       lappend ::CSF_OPT_INC "$aPath/include"
1154       if { "$::tcl_platform(platform)" == "windows" } {
1155         lappend ::CSF_OPT_INC "$aPath/include/win32"
1156       } elseif { [file exists "$aPath/include/linux"] } {
1157         lappend ::CSF_OPT_INC "$aPath/include/linux"
1158       }
1159     } else {
1160       if { [file exists "/System/Library/Frameworks/JavaVM.framework/Home/include/jni.h"] } {
1161         lappend ::CSF_OPT_INC "/System/Library/Frameworks/JavaVM.framework/Home/include"
1162       } else {
1163         lappend anErrInc "Error: 'jni.h' or 'jni_md.h' not found (JDK)"
1164         set isFound "false"
1165       }
1166     }
1167   }
1168
1169   foreach anArchIter {64 32} {
1170     set aJavacPath [wokdep:SearchBin "javac${::SYS_EXE_SUFFIX}" "$anArchIter"]
1171     if { "$aJavacPath" == "" } {
1172       set aPath [wokdep:Preferred [glob -nocomplain -directory "$::PRODUCTS_PATH" -type d *{jdk,java}*] "$::VCVER" "$anArchIter" ]
1173       set aJavacPath [wokdep:SearchBin "javac${::SYS_EXE_SUFFIX}" "$anArchIter" "$aPath/bin"]
1174       if { "$aJavacPath" != "" } {
1175         lappend ::CSF_OPT_BIN$anArchIter "$aPath/bin"
1176       } else {
1177         if { "$::ARCH" == "$anArchIter" && [file exists "/System/Library/Frameworks/JavaVM.framework/Home/bin/javac${::SYS_EXE_SUFFIX}"] } {
1178           lappend ::CSF_OPT_BIN$anArchIter "/System/Library/Frameworks/JavaVM.framework/Home/bin"
1179         } else {
1180           lappend anErrBin$anArchIter "Error: 'javac${::SYS_EXE_SUFFIX}' not found (JDK)"
1181           if { "$::ARCH" == "$anArchIter"} { set isFound "false" }
1182         }
1183       }
1184     }
1185   }
1186
1187   return "$isFound"
1188 }
1189
1190 # Search X11 libraries placement
1191 proc wokdep:SearchX11 {theErrInc theErrLib32 theErrLib64 theErrBin32 theErrBin64} {
1192   upvar $theErrInc   anErrInc
1193   upvar $theErrLib32 anErrLib32
1194   upvar $theErrLib64 anErrLib64
1195   upvar $theErrBin32 anErrBin32
1196   upvar $theErrBin64 anErrBin64
1197
1198   set isFound "true"
1199   if { "$::tcl_platform(platform)" == "windows" || ( "$::tcl_platform(os)" == "Darwin" && "$::HAVE_XLIB" != "true" ) } {
1200     return "$isFound"
1201   }
1202
1203   set aXmuLibPath [wokdep:SearchLib "Xmu" "$::ARCH"]
1204   if { "$aXmuLibPath" == "" } {
1205     set aXmuLibPath [wokdep:SearchLib "Xmu" "$::ARCH" "/usr/X11/lib"]
1206     if { "$aXmuLibPath" != "" } {
1207       #lappend ::CSF_OPT_LIB$::ARCH "/usr/X11/lib"
1208     } else {
1209       lappend anErrLib$::ARCH "Error: '${::SYS_LIB_PREFIX}Xmu.${::SYS_LIB_SUFFIX}' not found (X11)"
1210       set isFound "false"
1211     }
1212   }
1213
1214   return "$isFound"
1215 }
1216
1217 # Returns OCCT version string from file Standard_Version.hxx (if available)
1218 proc wokdep:DetectCasVersion {} {
1219   set occt_ver 7.0.0
1220   set aCasRoot [file normalize [file dirname [info script]]]
1221   set filename "${aCasRoot}/src/Standard/Standard_Version.hxx"
1222   if { [file exists $filename] } {
1223     set fh [open $filename "r"]
1224     set fh_loaded [read $fh]
1225     close $fh
1226     regexp {[^/]\s*#\s*define\s+OCC_VERSION_COMPLETE\s+\"([^\s]*)\"} $fh_loaded dummy occt_ver
1227   } else {
1228     puts "Error: file '$filename' not found"
1229   }
1230   return $occt_ver
1231 }
1232
1233 # Generate (override) custom environment file
1234 proc wokdep:SaveCustom {} {
1235   set aGenInfo "This environment file was generated by genconf.tcl script at [clock format [clock seconds] -format "%Y.%m.%d %H:%M"]"
1236   if { "$::tcl_platform(platform)" == "windows" } {
1237     set aCustomFilePath "./custom.bat"
1238     set aFile [open $aCustomFilePath "w"]
1239     puts $aFile "@echo off"
1240     puts $aFile "rem $aGenInfo"
1241
1242     puts $aFile ""
1243     puts $aFile "set PRJFMT=$::PRJFMT"
1244     puts $aFile "set VCVER=$::VCVER"
1245     puts $aFile "set ARCH=$::ARCH"
1246     puts $aFile "set VCVARS=$::VCVARS"
1247     puts $aFile "set SHORTCUT_HEADERS=$::SHORTCUT_HEADERS"
1248
1249     puts $aFile ""
1250     puts $aFile "set \"PRODUCTS_PATH=$::PRODUCTS_PATH\""
1251
1252     puts $aFile ""
1253     puts $aFile "rem Optional 3rd-parties switches"
1254     foreach anEnvIter $::THE_ENV_VARIABLES {
1255       set aName ${anEnvIter}
1256       set aValue [set ::${anEnvIter}]
1257       if { "$aValue" != "" } {
1258         puts $aFile "set ${aName}=$aValue"
1259       }
1260     }
1261
1262     set aStringInc [join $::CSF_OPT_INC $::SYS_PATH_SPLITTER]
1263     if { "$::PRODUCTS_PATH" != "" } {
1264       set aStringInc [regsub -all "$::PRODUCTS_PATH" $aStringInc "%PRODUCTS_PATH%"]
1265     }
1266     puts $aFile ""
1267     puts $aFile "rem Additional headers search paths"
1268     puts $aFile "set \"CSF_OPT_INC=$aStringInc\""
1269
1270     set aStringLib32 [join $::CSF_OPT_LIB32 $::SYS_PATH_SPLITTER]
1271     if { "$::PRODUCTS_PATH" != "" } {
1272       set aStringLib32 [regsub -all "$::PRODUCTS_PATH" $aStringLib32 "%PRODUCTS_PATH%"]
1273     }
1274     puts $aFile ""
1275     puts $aFile "rem Additional libraries (32-bit) search paths"
1276     puts $aFile "set \"CSF_OPT_LIB32=$aStringLib32\""
1277
1278     set aStringLib64 [join $::CSF_OPT_LIB64 $::SYS_PATH_SPLITTER]
1279     if { "$::PRODUCTS_PATH" != "" } {
1280       set aStringLib64 [regsub -all "$::PRODUCTS_PATH" $aStringLib64 "%PRODUCTS_PATH%"]
1281     }
1282     puts $aFile ""
1283     puts $aFile "rem Additional libraries (64-bit) search paths"
1284     puts $aFile "set \"CSF_OPT_LIB64=$aStringLib64\""
1285
1286     set aStringBin32 [join $::CSF_OPT_BIN32 $::SYS_PATH_SPLITTER]
1287     if { "$::PRODUCTS_PATH" != "" } {
1288       set aStringBin32 [regsub -all "$::PRODUCTS_PATH" $aStringBin32 "%PRODUCTS_PATH%"]
1289     }
1290     puts $aFile ""
1291     puts $aFile "rem Additional (32-bit) search paths"
1292     puts $aFile "set \"CSF_OPT_BIN32=$aStringBin32\""
1293
1294     set aStringBin64 [join $::CSF_OPT_BIN64 $::SYS_PATH_SPLITTER]
1295     if { "$::PRODUCTS_PATH" != "" } {
1296       set aStringBin64 [regsub -all "$::PRODUCTS_PATH" $aStringBin64 "%PRODUCTS_PATH%"]
1297     }
1298     puts $aFile ""
1299     puts $aFile "rem Additional (64-bit) search paths"
1300     puts $aFile "set \"CSF_OPT_BIN64=$aStringBin64\""
1301
1302     close $aFile
1303   } else {
1304     set aCustomFilePath "./custom.sh"
1305     set aFile [open $aCustomFilePath "w"]
1306     puts $aFile "#!/bin/bash"
1307     puts $aFile "# $aGenInfo"
1308
1309     puts $aFile ""
1310     puts $aFile "export PRJFMT=$::PRJFMT"
1311     puts $aFile "export ARCH=$::ARCH"
1312     puts $aFile "export SHORTCUT_HEADERS=$::SHORTCUT_HEADERS"
1313
1314     puts $aFile ""
1315     puts $aFile "export PRODUCTS_PATH=\"$::PRODUCTS_PATH\""
1316
1317     puts $aFile ""
1318     puts $aFile "# Optional 3rd-parties switches"
1319     foreach anEnvIter $::THE_ENV_VARIABLES {
1320       set aName ${anEnvIter}
1321       set aValue [set ::${anEnvIter}]
1322       if { "$aValue" != "" } {
1323         puts $aFile "export ${aName}=${aValue}"
1324       }
1325     }
1326
1327     set aStringInc [join $::CSF_OPT_INC $::SYS_PATH_SPLITTER]
1328     if { "$::PRODUCTS_PATH" != "" } {
1329       set aStringInc [regsub -all "$::PRODUCTS_PATH" $aStringInc "\${PRODUCTS_PATH}"]
1330     }
1331     puts $aFile ""
1332     puts $aFile "# Additional headers search paths"
1333     puts $aFile "export CSF_OPT_INC=\"$aStringInc\""
1334
1335     set aStringLib [join [set ::CSF_OPT_LIB$::ARCH] $::SYS_PATH_SPLITTER]
1336     if { "$::PRODUCTS_PATH" != "" } {
1337       set aStringLib [regsub -all "$::PRODUCTS_PATH" $aStringLib "\${PRODUCTS_PATH}"]
1338     }
1339     puts $aFile ""
1340     puts $aFile "# Additional libraries ($::ARCH-bit) search paths"
1341     puts $aFile "export CSF_OPT_LIB$::ARCH=\"[set aStringLib]\""
1342
1343     set aStringBin [join [set ::CSF_OPT_BIN$::ARCH] $::SYS_PATH_SPLITTER]
1344     if { "$::PRODUCTS_PATH" != "" } {
1345       set aStringBin [regsub -all "$::PRODUCTS_PATH" $aStringBin "\${PRODUCTS_PATH}"]
1346     }
1347     puts $aFile ""
1348     puts $aFile "# Additional ($::ARCH-bit) search paths"
1349     puts $aFile "export CSF_OPT_BIN$::ARCH=\"[set aStringBin]\""
1350
1351     close $aFile
1352   }
1353   puts "Configuration saved to file '$aCustomFilePath'"
1354
1355   # generate custom.auto.pri
1356   set toExportCustomPri 1
1357   if { $toExportCustomPri == 1 } {
1358     set aCasVer [wokdep:DetectCasVersion]
1359     set aCustomFilePath "./adm/qmake/custom.auto.pri"
1360     set aFile [open $aCustomFilePath "w"]
1361     puts $aFile "# $aGenInfo"
1362
1363     puts $aFile ""
1364     puts $aFile "VERSION=$aCasVer"
1365     puts $aFile "PRODUCTS_PATH=\"$::PRODUCTS_PATH\""
1366
1367     puts $aFile ""
1368     puts $aFile "# Optional 3rd-parties switches"
1369     foreach anEnvIter $::THE_ENV_VARIABLES {
1370       set aName ${anEnvIter}
1371       set aValue [set ::${anEnvIter}]
1372       if { "$aValue" == "true" } {
1373         puts $aFile "CONFIG += ${aName}"
1374       } else {
1375         #puts $aFile "CONFIG -= ${aName}"
1376       }
1377     }
1378
1379     puts $aFile ""
1380     puts $aFile "# Additional headers search paths"
1381     foreach anIncPath $::CSF_OPT_INC {
1382       if { "$::PRODUCTS_PATH" != "" } {
1383         set anIncPath [regsub -all "$::PRODUCTS_PATH" $anIncPath "\$\$\{PRODUCTS_PATH\}"]
1384       }
1385       puts $aFile "INCLUDEPATH += \"${anIncPath}\""
1386     }
1387
1388     puts $aFile ""
1389     puts $aFile "# Additional libraries search paths"
1390     foreach aLibPath [set ::CSF_OPT_LIB$::ARCH] {
1391       if { "$::PRODUCTS_PATH" != "" } {
1392         set aLibPath [regsub -all "$::PRODUCTS_PATH" $aLibPath "\$\$\{PRODUCTS_PATH\}"]
1393       }
1394       puts $aFile "LIBS += -L\"${aLibPath}\""
1395     }
1396
1397     if { "$::tcl_platform(platform)" == "windows" } {
1398       puts $aFile ""
1399       puts $aFile "# Additional DLLs search paths"
1400       foreach aDllPath [set ::CSF_OPT_BIN$::ARCH] {
1401         if { "$::PRODUCTS_PATH" != "" } {
1402           set aDllPath [regsub -all "$::PRODUCTS_PATH" $aDllPath "\$\$\{PRODUCTS_PATH\}"]
1403         }
1404         puts $aFile "LIBS += -L\"${aDllPath}\""
1405       }
1406     }
1407
1408     puts $aFile ""
1409     close $aFile
1410     puts "Configuration saved to file '$aCustomFilePath'"
1411   }
1412 }