0027514: Configuration, CMake - relative paths are not correctly handled for INSTALL_DIR
[occt.git] / adm / cmake / occt_macros.cmake
1 ##
2
3 if(OCCT_MACROS_ALREADY_INCLUDED)
4   return()
5 endif()
6 set(OCCT_MACROS_ALREADY_INCLUDED 1)
7
8
9 macro (OCCT_CHECK_AND_UNSET VARNAME)
10   if (DEFINED ${VARNAME})
11     unset (${VARNAME} CACHE)
12   endif()
13 endmacro()
14
15 macro (OCCT_CHECK_AND_UNSET_GROUP VARNAME)
16   OCCT_CHECK_AND_UNSET ("${VARNAME}_DIR")
17
18   OCCT_CHECK_AND_UNSET ("${VARNAME}_INCLUDE_DIR")
19
20   OCCT_CHECK_AND_UNSET ("${VARNAME}_LIBRARY")
21   OCCT_CHECK_AND_UNSET ("${VARNAME}_LIBRARY_DIR")
22
23   if (WIN32)
24     OCCT_CHECK_AND_UNSET ("${VARNAME}_DLL")
25     OCCT_CHECK_AND_UNSET ("${VARNAME}_DLL_DIR")
26   endif()
27 endmacro()
28
29 macro (OCCT_CHECK_AND_UNSET_INSTALL_DIR_SUBDIRS)
30   OCCT_CHECK_AND_UNSET (INSTALL_DIR_BIN)
31   OCCT_CHECK_AND_UNSET (INSTALL_DIR_SCRIPT)
32   OCCT_CHECK_AND_UNSET (INSTALL_DIR_LIB)
33   OCCT_CHECK_AND_UNSET (INSTALL_DIR_INCLUDE)
34   OCCT_CHECK_AND_UNSET (INSTALL_DIR_RESOURCE)
35   OCCT_CHECK_AND_UNSET (INSTALL_DIR_DATA)
36   OCCT_CHECK_AND_UNSET (INSTALL_DIR_SAMPLES)
37   OCCT_CHECK_AND_UNSET (INSTALL_DIR_TESTS)
38   OCCT_CHECK_AND_UNSET (INSTALL_DIR_DOC)
39 endmacro()
40
41 # COMPILER_BITNESS variable
42 macro (OCCT_MAKE_COMPILER_BITNESS)
43   math (EXPR COMPILER_BITNESS "32 + 32*(${CMAKE_SIZEOF_VOID_P}/8)")
44 endmacro()
45
46 # OS_WITH_BIT
47 macro (OCCT_MAKE_OS_WITH_BITNESS)
48
49   OCCT_MAKE_COMPILER_BITNESS()
50
51   if (WIN32)
52     set (OS_WITH_BIT "win${COMPILER_BITNESS}")
53   elseif(APPLE)
54     set (OS_WITH_BIT "mac${COMPILER_BITNESS}")
55   else()
56     set (OS_WITH_BIT "lin${COMPILER_BITNESS}")
57   endif()
58 endmacro()
59
60 # COMPILER variable
61 macro (OCCT_MAKE_COMPILER_SHORT_NAME)
62   if (MSVC)
63     if (MSVC70)
64       set (COMPILER vc7)
65     elseif (MSVC80)
66       set (COMPILER vc8)
67     elseif (MSVC90)
68       set (COMPILER vc9)
69     elseif (MSVC10)
70       set (COMPILER vc10)
71     elseif (MSVC11)
72       set (COMPILER vc11)
73     elseif (MSVC12)
74       set (COMPILER vc12)
75     elseif (MSVC14)
76       set (COMPILER vc14)
77     endif()
78   elseif (DEFINED CMAKE_COMPILER_IS_GNUCC)
79     set (COMPILER gcc)
80   elseif (DEFINED CMAKE_COMPILER_IS_GNUCXX)
81     set (COMPILER gxx)
82   elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
83     set (COMPILER clang)
84   elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
85     set (COMPILER icc)
86   else()
87     set (COMPILER ${CMAKE_GENERATOR})
88     string (REGEX REPLACE " " "" COMPILER ${COMPILER})
89   endif()
90 endmacro()
91
92 function (SUBDIRECTORY_NAMES MAIN_DIRECTORY RESULT)
93   file (GLOB SUB_ITEMS "${MAIN_DIRECTORY}/*")
94
95   foreach (ITEM ${SUB_ITEMS})
96     if (IS_DIRECTORY "${ITEM}")
97       get_filename_component (ITEM_NAME "${ITEM}" NAME)
98       list (APPEND LOCAL_RESULT "${ITEM_NAME}")
99     endif()
100   endforeach()
101   set (${RESULT} ${LOCAL_RESULT} PARENT_SCOPE)
102 endfunction()
103
104 function (OCCT_ORIGIN_AND_PATCHED_FILES RELATIVE_PATH SEARCH_TEMPLATE RESULT)
105
106   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_PATH}")
107     file (GLOB FOUND_FILES "${BUILD_PATCH}/${RELATIVE_PATH}/${SEARCH_TEMPLATE}")
108   endif()
109
110   file (GLOB ORIGIN_FILES "${CMAKE_SOURCE_DIR}/${RELATIVE_PATH}/${SEARCH_TEMPLATE}")
111   foreach (ORIGIN_FILE ${ORIGIN_FILES})
112     # check for existence of patched version of current file
113     if (NOT BUILD_PATCH OR NOT EXISTS "${BUILD_PATCH}/${RELATIVE_PATH}")
114       list (APPEND FOUND_FILES ${ORIGIN_FILE})
115     else()
116       get_filename_component (ORIGIN_FILE_NAME "${ORIGIN_FILE}" NAME)
117       if (NOT EXISTS "${BUILD_PATCH}/${RELATIVE_PATH}/${ORIGIN_FILE_NAME}")
118         list (APPEND FOUND_FILES ${ORIGIN_FILE})
119       endif()
120     endif()
121   endforeach()
122
123   set (${RESULT} ${FOUND_FILES} PARENT_SCOPE)
124 endfunction()
125
126 function (FIND_PRODUCT_DIR ROOT_DIR PRODUCT_NAME RESULT)
127   OCCT_MAKE_COMPILER_SHORT_NAME()
128   OCCT_MAKE_COMPILER_BITNESS()
129
130   string (TOLOWER "${PRODUCT_NAME}" lower_PRODUCT_NAME)
131
132   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*${COMPILER}.*${COMPILER_BITNESS}")
133   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*[0-9.]+.*${COMPILER}.*${COMPILER_BITNESS}")
134   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*[0-9.]+.*${COMPILER_BITNESS}")
135   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*.*${COMPILER_BITNESS}")
136   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*[0-9.]+")
137   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*")
138
139   SUBDIRECTORY_NAMES ("${ROOT_DIR}" SUBDIR_NAME_LIST)
140
141   foreach (SEARCH_TEMPLATE ${SEARCH_TEMPLATES})
142     if (LOCAL_RESULT)
143       BREAK()
144     endif()
145
146     foreach (SUBDIR_NAME ${SUBDIR_NAME_LIST})
147       string (TOLOWER "${SUBDIR_NAME}" lower_SUBDIR_NAME)
148
149       string (REGEX MATCH "${SEARCH_TEMPLATE}" DUMMY_VAR "${lower_SUBDIR_NAME}")
150       if (DUMMY_VAR)
151         list (APPEND LOCAL_RESULT ${SUBDIR_NAME})
152       endif()
153     endforeach()
154   endforeach()
155
156   if (LOCAL_RESULT)
157     list (GET LOCAL_RESULT -1 DUMMY)
158     set (${RESULT} ${DUMMY} PARENT_SCOPE)
159   endif()
160 endfunction()
161
162 macro (OCCT_INSTALL_FILE_OR_DIR BEING_INSTALLED_OBJECT DESTINATION_PATH)
163   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_INSTALLED_OBJECT}")
164     if (IS_DIRECTORY "${BUILD_PATCH}/${BEING_INSTALLED_OBJECT}")
165       # first of all, install original files
166       install (DIRECTORY "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
167
168       # secondly, rewrite original files with patched ones
169       install (DIRECTORY "${BUILD_PATCH}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
170     else()
171       install (FILES     "${BUILD_PATCH}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
172     endif()
173   else()
174     if (IS_DIRECTORY "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}")
175       install (DIRECTORY "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
176     else()
177       install (FILES     "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
178     endif()
179   endif()
180 endmacro()
181
182 macro (OCCT_CONFIGURE_AND_INSTALL BEING_CONGIRUGED_FILE BUILD_NAME INSTALL_NAME DESTINATION_PATH)
183   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_CONGIRUGED_FILE}")
184     configure_file("${BUILD_PATCH}/${BEING_CONGIRUGED_FILE}" "${BUILD_NAME}" @ONLY)
185   else()
186     configure_file("${CMAKE_SOURCE_DIR}/${BEING_CONGIRUGED_FILE}" "${BUILD_NAME}" @ONLY)
187   endif()
188
189   install(FILES "${OCCT_BINARY_DIR}/${BUILD_NAME}" DESTINATION  "${DESTINATION_PATH}" RENAME ${INSTALL_NAME})
190 endmacro()
191
192 macro (COLLECT_AND_INSTALL_OCCT_HEADER_FILES ROOT_TARGET_OCCT_DIR OCCT_BUILD_TOOLKITS)
193   set (OCCT_USED_PACKAGES)
194
195   # consider patched header.in template
196   set (TEMPLATE_HEADER_PATH "${CMAKE_SOURCE_DIR}/adm/templates/header.in")
197   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/adm/templates/header.in")
198     set (TEMPLATE_HEADER_PATH "${BUILD_PATCH}/adm/templates/header.in")
199   endif()
200
201   set (ROOT_OCCT_DIR ${CMAKE_SOURCE_DIR})
202
203   foreach (OCCT_USED_TOOLKIT ${OCCT_BUILD_TOOLKITS})
204     # append all required package folders
205     set (OCCT_TOOLKIT_PACKAGES)
206     if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${OCCT_USED_TOOLKIT}/PACKAGES")
207       file (STRINGS "${BUILD_PATCH}/src/${OCCT_USED_TOOLKIT}/PACKAGES" OCCT_TOOLKIT_PACKAGES)
208     elseif (EXISTS "${CMAKE_SOURCE_DIR}/src/${OCCT_USED_TOOLKIT}/PACKAGES")
209       file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_USED_TOOLKIT}/PACKAGES" OCCT_TOOLKIT_PACKAGES)
210     endif()
211
212     list (APPEND OCCT_USED_PACKAGES ${OCCT_TOOLKIT_PACKAGES})
213   endforeach()
214
215   list (REMOVE_DUPLICATES OCCT_USED_PACKAGES)
216
217   set (OCCT_HEADER_FILES_COMPLETE)
218   set (OCCT_HEADER_FILE_NAMES_NOT_IN_FILES)
219   set (OCCT_HEADER_FILE_WITH_PROPER_NAMES)
220
221   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
222   message (STATUS "Info: \(${CURRENT_TIME}\) Compare FILES with files in package directories...")
223
224   foreach (OCCT_PACKAGE ${OCCT_USED_PACKAGES})
225     if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES")
226       file (STRINGS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES" OCCT_ALL_FILE_NAMES)
227     elseif (EXISTS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES")
228       file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" OCCT_ALL_FILE_NAMES)
229     else()
230       message (WARNING "FILES has not been found in ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}")
231       continue()
232     endif()
233
234     list (LENGTH OCCT_ALL_FILE_NAMES ALL_FILES_NB)
235     math (EXPR ALL_FILES_NB "${ALL_FILES_NB} - 1" )
236
237     # emit warnings if there is unprocessed headers
238     file (GLOB OCCT_ALL_FILES_IN_DIR "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/*.*")
239     file (GLOB OCCT_ALL_FILES_IN_PATCH_DIR "${BUILD_PATCH}/src/${OCCT_PACKAGE}/*.*")
240
241     # use patched header files
242     foreach (OCCT_FILE_IN_PATCH_DIR ${OCCT_ALL_FILES_IN_PATCH_DIR})
243       get_filename_component (OCCT_FILE_IN_PATCH_DIR_NAME ${OCCT_FILE_IN_PATCH_DIR} NAME)
244       list (REMOVE_ITEM OCCT_ALL_FILES_IN_DIR "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${OCCT_FILE_IN_PATCH_DIR_NAME}")
245       list (APPEND OCCT_ALL_FILES_IN_DIR "${OCCT_FILE_IN_PATCH_DIR}")
246     endforeach()
247
248     foreach (OCCT_FILE_IN_DIR ${OCCT_ALL_FILES_IN_DIR})
249       get_filename_component (OCCT_FILE_IN_DIR_NAME ${OCCT_FILE_IN_DIR} NAME)
250
251       set (OCCT_FILE_IN_DIR_STATUS OFF)
252
253       if (${ALL_FILES_NB} LESS 0)
254         break()
255       endif()
256
257       foreach (FILE_INDEX RANGE ${ALL_FILES_NB})
258         list (GET OCCT_ALL_FILE_NAMES ${FILE_INDEX} OCCT_FILE_NAME)
259
260         if ("${OCCT_FILE_IN_DIR_NAME}" STREQUAL "${OCCT_FILE_NAME}")
261           set (OCCT_FILE_IN_DIR_STATUS ON)
262
263           string (REGEX MATCH ".+\\.[hlg]xx|.+\\.h$" IS_HEADER_FOUND "${OCCT_FILE_NAME}")
264           if (IS_HEADER_FOUND)
265             list (APPEND OCCT_HEADER_FILES_COMPLETE ${OCCT_FILE_IN_DIR})
266
267             # collect header files with name that does not contain its package one
268             string (FIND "${OCCT_FILE_NAME}" "${OCCT_PACKAGE}_" FOUND_INDEX)
269             if (NOT ${FOUND_INDEX} EQUAL 0)
270               list (APPEND OCCT_HEADER_FILE_WITH_PROPER_NAMES "${OCCT_FILE_NAME}")
271             endif()
272           endif()
273
274           # remove found element from list
275           list (REMOVE_AT OCCT_ALL_FILE_NAMES ${FILE_INDEX})
276           math (EXPR ALL_FILES_NB "${ALL_FILES_NB} - 1" ) # decrement number
277
278           break()
279         endif()
280       endforeach()
281
282       if (NOT OCCT_FILE_IN_DIR_STATUS)
283         message (STATUS "Warning. File ${OCCT_FILE_IN_DIR} is not listed in ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES")
284
285         string (REGEX MATCH ".+\\.[hlg]xx|.+\\.h$" IS_HEADER_FOUND "${OCCT_FILE_NAME}")
286         if (IS_HEADER_FOUND)
287           list (APPEND OCCT_HEADER_FILE_NAMES_NOT_IN_FILES ${OCCT_FILE_NAME})
288         endif()
289       endif()
290     endforeach()
291   endforeach()
292   
293   # create new file including found header
294   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
295   message (STATUS "Info: \(${CURRENT_TIME}\) Create header-links in inc folder...")
296
297   foreach (OCCT_HEADER_FILE ${OCCT_HEADER_FILES_COMPLETE})
298     get_filename_component (HEADER_FILE_NAME ${OCCT_HEADER_FILE} NAME)
299     configure_file ("${TEMPLATE_HEADER_PATH}" "${ROOT_TARGET_OCCT_DIR}/inc/${HEADER_FILE_NAME}" @ONLY)
300   endforeach()
301   
302   install (FILES ${OCCT_HEADER_FILES_COMPLETE} DESTINATION "${INSTALL_DIR_INCLUDE}")
303   
304   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
305   message (STATUS "Info: \(${CURRENT_TIME}\) Checking headers in inc folder...")
306     
307   file (GLOB OCCT_HEADER_FILES_OLD "${ROOT_TARGET_OCCT_DIR}/inc/*")
308   foreach (OCCT_HEADER_FILE_OLD ${OCCT_HEADER_FILES_OLD})
309     get_filename_component (HEADER_FILE_NAME ${OCCT_HEADER_FILE_OLD} NAME)
310     string (REGEX MATCH "^[a-zA-Z0-9]+" PACKAGE_NAME "${HEADER_FILE_NAME}")
311     
312     list (FIND OCCT_USED_PACKAGES ${PACKAGE_NAME} IS_HEADER_FOUND)
313     if (NOT ${IS_HEADER_FOUND} EQUAL -1)
314       if (NOT EXISTS "${CMAKE_SOURCE_DIR}/src/${PACKAGE_NAME}/${HEADER_FILE_NAME}")
315         message (STATUS "Warning. ${OCCT_HEADER_FILE_OLD} is not presented in the sources and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
316         file (REMOVE "${OCCT_HEADER_FILE_OLD}")
317       else()
318         list (FIND OCCT_HEADER_FILE_NAMES_NOT_IN_FILES ${PACKAGE_NAME} IS_HEADER_FOUND)
319         if (NOT ${IS_HEADER_FOUND} EQUAL -1)
320           message (STATUS "Warning. ${OCCT_HEADER_FILE_OLD} is presented in the sources but not involved in FILES and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
321           file (REMOVE "${OCCT_HEADER_FILE_OLD}")
322         endif()
323       endif()
324     else()
325       set (IS_HEADER_FOUND -1)
326       if (NOT "${OCCT_HEADER_FILE_WITH_PROPER_NAMES}" STREQUAL "")
327         list (FIND OCCT_HEADER_FILE_WITH_PROPER_NAMES ${HEADER_FILE_NAME} IS_HEADER_FOUND)
328       endif()
329       
330       if (${IS_HEADER_FOUND} EQUAL -1)
331         message (STATUS "Warning. \(${PACKAGE_NAME}\) ${OCCT_HEADER_FILE_OLD} is not used and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
332         file (REMOVE "${OCCT_HEADER_FILE_OLD}")
333       endif()
334     endif()
335   endforeach()
336 endmacro()
337
338 macro (OCCT_COPY_FILE_OR_DIR BEING_COPIED_OBJECT DESTINATION_PATH)
339   # first of all, copy original files
340   if (EXISTS "${CMAKE_SOURCE_DIR}/${BEING_COPIED_OBJECT}")
341     file (COPY "${CMAKE_SOURCE_DIR}/${BEING_COPIED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
342   endif()
343
344   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_COPIED_OBJECT}")
345     # secondly, rewrite original files with patched ones
346     file (COPY "${BUILD_PATCH}/${BEING_COPIED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
347   endif()
348 endmacro()
349
350 macro (OCCT_CONFIGURE BEING_CONGIRUGED_FILE FINAL_NAME)
351   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_CONGIRUGED_FILE}")
352     configure_file("${BUILD_PATCH}/${BEING_CONGIRUGED_FILE}" "${FINAL_NAME}" @ONLY)
353   else()
354     configure_file("${CMAKE_SOURCE_DIR}/${BEING_CONGIRUGED_FILE}" "${FINAL_NAME}" @ONLY)
355   endif()
356 endmacro()
357
358 macro (OCCT_ADD_SUBDIRECTORY BEING_ADDED_DIRECTORY)
359   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_ADDED_DIRECTORY}/CMakeLists.txt")
360     add_subdirectory(${BUILD_PATCH}/${BEING_ADDED_DIRECTORY})
361   elseif (EXISTS "${CMAKE_SOURCE_DIR}/${BEING_ADDED_DIRECTORY}/CMakeLists.txt")
362     add_subdirectory (${CMAKE_SOURCE_DIR}/${BEING_ADDED_DIRECTORY})
363   else()
364     message (STATUS "${BEING_ADDED_DIRECTORY} directory is not included")
365   endif()
366 endmacro()
367
368 function (OCCT_IS_PRODUCT_REQUIRED CSF_VAR_NAME USE_PRODUCT)
369   set (${USE_PRODUCT} OFF PARENT_SCOPE)
370
371   if (NOT BUILD_TOOLKITS)
372     message(STATUS "Warning: the list of being used toolkits is empty")
373   else()
374     foreach (USED_TOOLKIT ${BUILD_TOOLKITS})
375       if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${USED_TOOLKIT}/EXTERNLIB")
376         file (READ "${BUILD_PATCH}/src/${USED_TOOLKIT}/EXTERNLIB" FILE_CONTENT)
377       elseif (EXISTS "${CMAKE_SOURCE_DIR}/src/${USED_TOOLKIT}/EXTERNLIB")
378         file (READ "${CMAKE_SOURCE_DIR}/src/${USED_TOOLKIT}/EXTERNLIB" FILE_CONTENT)
379       endif()
380
381       string (REGEX MATCH "${CSF_VAR_NAME}" DOES_FILE_CONTAIN "${FILE_CONTENT}")
382
383       if (DOES_FILE_CONTAIN)
384         set (${USE_PRODUCT} ON PARENT_SCOPE)
385         break()
386       endif()
387     endforeach()
388   endif()
389 endfunction()
390
391 function (FILE_TO_LIST FILE_NAME FILE_CONTENT)
392   set (LOCAL_FILE_CONTENT)
393   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${FILE_NAME}")
394     file (STRINGS "${BUILD_PATCH}/${FILE_NAME}" LOCAL_FILE_CONTENT)
395   elseif (EXISTS "${CMAKE_SOURCE_DIR}/${FILE_NAME}")
396     file (STRINGS "${CMAKE_SOURCE_DIR}/${FILE_NAME}" LOCAL_FILE_CONTENT)
397   endif()
398
399   set (${FILE_CONTENT} ${LOCAL_FILE_CONTENT} PARENT_SCOPE)
400 endfunction()
401
402 # Function to determine if TOOLKIT is OCCT toolkit
403 function (IS_OCCT_TOOLKIT TOOLKIT_NAME MODULES IS_TOOLKIT_FOUND)
404   set (${IS_TOOLKIT_FOUND} OFF PARENT_SCOPE)
405   foreach (MODULE ${${MODULES}})
406     set (TOOLKITS ${${MODULE}_TOOLKITS})
407     list (FIND TOOLKITS ${TOOLKIT_NAME} FOUND)
408
409     if (NOT ${FOUND} EQUAL -1)
410       set (${IS_TOOLKIT_FOUND} ON PARENT_SCOPE)
411     endif()
412   endforeach(MODULE)
413 endfunction()
414
415 # TOOLKIT_DEPS is defined with dependencies from file src/TOOLKIT_NAME/EXTERNLIB.
416 # CSF_ variables are ignored
417 function (OCCT_TOOLKIT_DEP TOOLKIT_NAME TOOLKIT_DEPS)
418   FILE_TO_LIST ("src/${TOOLKIT_NAME}/EXTERNLIB" FILE_CONTENT)
419
420   #list (APPEND LOCAL_TOOLKIT_DEPS ${TOOLKIT_NAME})
421   set (LOCAL_TOOLKIT_DEPS)
422   foreach (FILE_CONTENT_LINE ${FILE_CONTENT})
423     string (REGEX MATCH "^TK" TK_FOUND ${FILE_CONTENT_LINE})
424     if ("${FILE_CONTENT_LINE}" STREQUAL "DRAWEXE" OR NOT "${TK_FOUND}" STREQUAL "")
425       list (APPEND LOCAL_TOOLKIT_DEPS ${FILE_CONTENT_LINE})
426     endif()
427   endforeach()
428
429   set (${TOOLKIT_DEPS} ${LOCAL_TOOLKIT_DEPS} PARENT_SCOPE)
430 endfunction()
431
432 # TOOLKIT_FULL_DEPS is defined with complete dependencies (all levels)
433 function (OCCT_TOOLKIT_FULL_DEP TOOLKIT_NAME TOOLKIT_FULL_DEPS)
434   # first level dependencies are stored in LOCAL_TOOLKIT_FULL_DEPS
435   OCCT_TOOLKIT_DEP (${TOOLKIT_NAME} LOCAL_TOOLKIT_FULL_DEPS)
436
437   list (LENGTH LOCAL_TOOLKIT_FULL_DEPS LIST_LENGTH)
438   set (LIST_INDEX 0)
439   while (LIST_INDEX LESS LIST_LENGTH)
440     list (GET LOCAL_TOOLKIT_FULL_DEPS ${LIST_INDEX} CURRENT_TOOLKIT)
441     OCCT_TOOLKIT_DEP (${CURRENT_TOOLKIT} CURRENT_TOOLKIT_DEPS)
442
443     # append toolkits are not contained
444     foreach (CURRENT_TOOLKIT_DEP ${CURRENT_TOOLKIT_DEPS})
445       set (CURRENT_TOOLKIT_DEP_FOUND OFF)
446       foreach (LOCAL_TOOLKIT_FULL_DEP ${LOCAL_TOOLKIT_FULL_DEPS})
447         if ("${CURRENT_TOOLKIT_DEP}" STREQUAL "${LOCAL_TOOLKIT_FULL_DEP}")
448           set (CURRENT_TOOLKIT_DEP_FOUND ON)
449           break()
450         endif()
451       endforeach()
452       if ("${CURRENT_TOOLKIT_DEP_FOUND}" STREQUAL "OFF")
453         list (APPEND LOCAL_TOOLKIT_FULL_DEPS ${CURRENT_TOOLKIT_DEP})
454       endif()
455     endforeach()
456
457     # increment the list index
458     MATH(EXPR LIST_INDEX "${LIST_INDEX}+1")
459
460     # calculate new length
461     list (LENGTH LOCAL_TOOLKIT_FULL_DEPS LIST_LENGTH)
462   endwhile()
463
464   set (${TOOLKIT_FULL_DEPS} ${LOCAL_TOOLKIT_FULL_DEPS} PARENT_SCOPE)
465 endfunction()
466
467 # Function to get list of modules and toolkits from file adm/MODULES.
468 # Creates list <$MODULE_LIST> to store list of MODULES and
469 # <NAME_OF_MODULE>_TOOLKITS foreach module to store its toolkits.
470 function (OCCT_MODULES_AND_TOOLKITS MODULE_LIST)
471   FILE_TO_LIST ("adm/MODULES" FILE_CONTENT)
472
473   foreach (CONTENT_LINE ${FILE_CONTENT})
474     string (REPLACE " " ";" CONTENT_LINE ${CONTENT_LINE})
475     list (GET CONTENT_LINE 0 MODULE_NAME)
476     list (REMOVE_AT CONTENT_LINE 0)
477     list (APPEND ${MODULE_LIST} ${MODULE_NAME})
478     # (!) REMOVE THE LINE BELOW (implicit variables)
479     set (${MODULE_NAME}_TOOLKITS ${CONTENT_LINE} PARENT_SCOPE)
480   endforeach()
481
482   set (${MODULE_LIST} ${${MODULE_LIST}} PARENT_SCOPE)
483 endfunction()
484
485 # Returns OCC version string from file Standard_Version.hxx (if available)
486 function (OCC_VERSION OCC_VERSION_MAJOR OCC_VERSION_MINOR OCC_VERSION_MAINTENANCE OCC_VERSION_DEVELOPMENT OCC_VERSION_STRING_EXT)
487
488   set (OCC_VERSION_MAJOR         7)
489   set (OCC_VERSION_MINOR         0)
490   set (OCC_VERSION_MAINTENANCE   0)
491   set (OCC_VERSION_DEVELOPMENT   dev)
492   set (OCC_VERSION_COMPLETE      "7.0.0")
493  
494   set (STANDARD_VERSION_FILE "${CMAKE_SOURCE_DIR}/src/Standard/Standard_Version.hxx")
495   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/Standard/Standard_Version.hxx")
496     set (STANDARD_VERSION_FILE "${BUILD_PATCH}/src/Standard/Standard_Version.hxx")
497   endif()
498
499   if (EXISTS "${STANDARD_VERSION_FILE}")
500     foreach (SOUGHT_VERSION OCC_VERSION_MAJOR OCC_VERSION_MINOR OCC_VERSION_MAINTENANCE)
501       file (STRINGS "${STANDARD_VERSION_FILE}" ${SOUGHT_VERSION} REGEX "^#define ${SOUGHT_VERSION} .*")
502       string (REGEX REPLACE ".*${SOUGHT_VERSION} .*([^ ]+).*" "\\1" ${SOUGHT_VERSION} "${${SOUGHT_VERSION}}" )
503     endforeach()
504     
505     foreach (SOUGHT_VERSION OCC_VERSION_DEVELOPMENT OCC_VERSION_COMPLETE)
506       file (STRINGS "${STANDARD_VERSION_FILE}" ${SOUGHT_VERSION} REGEX "^#define ${SOUGHT_VERSION} .*")
507       string (REGEX REPLACE ".*${SOUGHT_VERSION} .*\"([^ ]+)\".*" "\\1" ${SOUGHT_VERSION} "${${SOUGHT_VERSION}}" )
508     endforeach()
509   endif()
510  
511   set (OCC_VERSION_MAJOR "${OCC_VERSION_MAJOR}" PARENT_SCOPE)
512   set (OCC_VERSION_MINOR "${OCC_VERSION_MINOR}" PARENT_SCOPE)
513   set (OCC_VERSION_MAINTENANCE "${OCC_VERSION_MAINTENANCE}" PARENT_SCOPE)
514   set (OCC_VERSION_DEVELOPMENT "${OCC_VERSION_DEVELOPMENT}" PARENT_SCOPE)
515   
516   if (OCC_VERSION_DEVELOPMENT AND OCC_VERSION_COMPLETE)
517     set (OCC_VERSION_STRING_EXT "${OCC_VERSION_COMPLETE}.${OCC_VERSION_DEVELOPMENT}" PARENT_SCOPE)
518   else()
519     set (OCC_VERSION_STRING_EXT "${OCC_VERSION_COMPLETE}" PARENT_SCOPE)
520   endif()
521 endfunction()
522
523 macro (CHECK_PATH_FOR_CONSISTENCY THE_ROOT_PATH_NAME THE_BEING_CHECKED_PATH_NAME THE_VAR_TYPE THE_MESSAGE_OF_BEING_CHECKED_PATH)
524   
525   set (THE_ROOT_PATH "${${THE_ROOT_PATH_NAME}}")
526   set (THE_BEING_CHECKED_PATH "${${THE_BEING_CHECKED_PATH_NAME}}")
527
528   if (THE_BEING_CHECKED_PATH OR EXISTS "${THE_BEING_CHECKED_PATH}")
529     get_filename_component (THE_ROOT_PATH_ABS "${THE_ROOT_PATH}" ABSOLUTE)
530     get_filename_component (THE_BEING_CHECKED_PATH_ABS "${THE_BEING_CHECKED_PATH}" ABSOLUTE)
531
532     string (REGEX MATCH "${THE_ROOT_PATH_ABS}" DOES_PATH_CONTAIN "${THE_BEING_CHECKED_PATH_ABS}")
533
534     if (NOT DOES_PATH_CONTAIN) # if cmake found the being checked path at different place from THE_ROOT_PATH_ABS
535       set (${THE_BEING_CHECKED_PATH_NAME} "" CACHE ${THE_VAR_TYPE} "${THE_MESSAGE_OF_BEING_CHECKED_PATH}" FORCE)
536     endif()
537   else()
538     set (${THE_BEING_CHECKED_PATH_NAME} "" CACHE ${THE_VAR_TYPE} "${THE_MESSAGE_OF_BEING_CHECKED_PATH}" FORCE)
539   endif()
540
541 endmacro()
542
543 # Adds OCCT_INSTALL_BIN_LETTER variable ("" for Release, "d" for Debug and 
544 # "i" for RelWithDebInfo) in OpenCASCADETargets-*.cmake files during 
545 # installation process.
546 # This and the following macros are used to overcome limitation of CMake
547 # prior to version 3.3 not supporting per-configuration install paths
548 # for install target files (see https://cmake.org/Bug/view.php?id=14317)
549 macro (OCCT_UPDATE_TARGET_FILE)
550   if (NOT SINGLE_GENERATOR)
551     OCCT_INSERT_CODE_FOR_TARGET ()
552   endif()
553
554   install (CODE
555   "cmake_policy(PUSH)
556   cmake_policy(SET CMP0007 NEW)
557   string (TOLOWER \"\${CMAKE_INSTALL_CONFIG_NAME}\" CMAKE_INSTALL_CONFIG_NAME_LOWERCASE)
558   file (GLOB ALL_OCCT_TARGET_FILES \"${INSTALL_DIR}/${INSTALL_DIR_CMAKE}/OpenCASCADE*Targets-\${CMAKE_INSTALL_CONFIG_NAME_LOWERCASE}.cmake\")
559   foreach(TARGET_FILENAME \${ALL_OCCT_TARGET_FILES})
560     file (STRINGS \"\${TARGET_FILENAME}\" TARGET_FILE_CONTENT)
561     file (REMOVE \"\${TARGET_FILENAME}\")
562     foreach (line IN LISTS TARGET_FILE_CONTENT)
563       string (REGEX REPLACE \"[\\\\]?[\\\$]{OCCT_INSTALL_BIN_LETTER}\" \"\${OCCT_INSTALL_BIN_LETTER}\" line \"\${line}\")
564       file (APPEND \"\${TARGET_FILENAME}\" \"\${line}\\n\")
565     endforeach()
566   endforeach()
567   cmake_policy(POP)")
568 endmacro()
569
570 macro (OCCT_INSERT_CODE_FOR_TARGET)
571   install(CODE "if (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$\")
572     set (OCCT_INSTALL_BIN_LETTER \"\")
573   elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$\")
574     set (OCCT_INSTALL_BIN_LETTER \"i\")
575   elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
576     set (OCCT_INSTALL_BIN_LETTER \"d\")
577   endif()")
578 endmacro()
579
580 macro (OCCT_UPDATE_DRAW_DEFAULT_FILE)
581   install(CODE "cmake_policy(PUSH)
582   cmake_policy(SET CMP0007 NEW)
583   set (DRAW_DEFAULT_FILE_NAME \"${INSTALL_DIR}/${INSTALL_DIR_RESOURCE}/DrawResources/DrawPlugin\")
584   file (STRINGS \"\${DRAW_DEFAULT_FILE_NAME}\" DRAW_DEFAULT_CONTENT)
585   file (REMOVE \"\${DRAW_DEFAULT_FILE_NAME}\")
586   foreach (line IN LISTS DRAW_DEFAULT_CONTENT)
587     string (REGEX MATCH \": TK\([a-zA-Z]+\)$\" IS_TK_LINE \"\${line}\")
588     string (REGEX REPLACE \": TK\([a-zA-Z]+\)$\" \": TK\${CMAKE_MATCH_1}${BUILD_SHARED_LIBRARY_NAME_POSTFIX}\" line \"\${line}\")
589     file (APPEND \"\${DRAW_DEFAULT_FILE_NAME}\" \"\${line}\\n\")
590   endforeach()
591   cmake_policy(POP)")
592 endmacro()
593
594 macro (OCCT_CREATE_SYMLINK_TO_FILE LIBRARY_NAME LINK_NAME)
595   if (NOT WIN32)
596     install (CODE "if (EXISTS \"${LIBRARY_NAME}\")
597         execute_process (COMMAND ln -s \"${LIBRARY_NAME}\" \"${LINK_NAME}\")
598       endif()
599     ")
600   endif()
601 endmacro()