2385743a036cfd79f951ea48238cf544f0f8abe6
[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         string (REGEX REPLACE "[^:]+:+" "" OCCT_FILE_NAME "${OCCT_FILE_NAME}")
261
262         if ("${OCCT_FILE_IN_DIR_NAME}" STREQUAL "${OCCT_FILE_NAME}")
263           set (OCCT_FILE_IN_DIR_STATUS ON)
264
265           string (REGEX MATCH ".+\\.[hlg]xx|.+\\.h$" IS_HEADER_FOUND "${OCCT_FILE_NAME}")
266           if (IS_HEADER_FOUND)
267             list (APPEND OCCT_HEADER_FILES_COMPLETE ${OCCT_FILE_IN_DIR})
268
269             # collect header files with name that does not contain its package one
270             string (FIND "${OCCT_FILE_NAME}" "${OCCT_PACKAGE}_" FOUND_INDEX)
271             if (NOT ${FOUND_INDEX} EQUAL 0)
272               list (APPEND OCCT_HEADER_FILE_WITH_PROPER_NAMES "${OCCT_FILE_NAME}")
273             endif()
274           endif()
275
276           # remove found element from list
277           list (REMOVE_AT OCCT_ALL_FILE_NAMES ${FILE_INDEX})
278           math (EXPR ALL_FILES_NB "${ALL_FILES_NB} - 1" ) # decrement number
279
280           break()
281         endif()
282       endforeach()
283
284       if (NOT OCCT_FILE_IN_DIR_STATUS)
285         message (STATUS "Warning. File ${OCCT_FILE_IN_DIR} is not listed in ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES")
286
287         string (REGEX MATCH ".+\\.[hlg]xx|.+\\.h$" IS_HEADER_FOUND "${OCCT_FILE_NAME}")
288         if (IS_HEADER_FOUND)
289           list (APPEND OCCT_HEADER_FILE_NAMES_NOT_IN_FILES ${OCCT_FILE_NAME})
290         endif()
291       endif()
292     endforeach()
293   endforeach()
294   
295   # create new file including found header
296   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
297   message (STATUS "Info: \(${CURRENT_TIME}\) Create header-links in inc folder...")
298
299   foreach (OCCT_HEADER_FILE ${OCCT_HEADER_FILES_COMPLETE})
300     get_filename_component (HEADER_FILE_NAME ${OCCT_HEADER_FILE} NAME)
301     set (OCCT_HEADER_FILE_CONTENT "#include \"${OCCT_HEADER_FILE}\"")
302     configure_file ("${TEMPLATE_HEADER_PATH}" "${ROOT_TARGET_OCCT_DIR}/inc/${HEADER_FILE_NAME}" @ONLY)
303   endforeach()
304   
305   install (FILES ${OCCT_HEADER_FILES_COMPLETE} DESTINATION "${INSTALL_DIR_INCLUDE}")
306   
307   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
308   message (STATUS "Info: \(${CURRENT_TIME}\) Checking headers in inc folder...")
309     
310   file (GLOB OCCT_HEADER_FILES_OLD "${ROOT_TARGET_OCCT_DIR}/inc/*")
311   foreach (OCCT_HEADER_FILE_OLD ${OCCT_HEADER_FILES_OLD})
312     get_filename_component (HEADER_FILE_NAME ${OCCT_HEADER_FILE_OLD} NAME)
313     string (REGEX MATCH "^[a-zA-Z0-9]+" PACKAGE_NAME "${HEADER_FILE_NAME}")
314     
315     list (FIND OCCT_USED_PACKAGES ${PACKAGE_NAME} IS_HEADER_FOUND)
316     if (NOT ${IS_HEADER_FOUND} EQUAL -1)
317       if (NOT EXISTS "${CMAKE_SOURCE_DIR}/src/${PACKAGE_NAME}/${HEADER_FILE_NAME}")
318         message (STATUS "Warning. ${OCCT_HEADER_FILE_OLD} is not presented in the sources and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
319         file (REMOVE "${OCCT_HEADER_FILE_OLD}")
320       else()
321         list (FIND OCCT_HEADER_FILE_NAMES_NOT_IN_FILES ${PACKAGE_NAME} IS_HEADER_FOUND)
322         if (NOT ${IS_HEADER_FOUND} EQUAL -1)
323           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")
324           file (REMOVE "${OCCT_HEADER_FILE_OLD}")
325         endif()
326       endif()
327     else()
328       set (IS_HEADER_FOUND -1)
329       if (NOT "${OCCT_HEADER_FILE_WITH_PROPER_NAMES}" STREQUAL "")
330         list (FIND OCCT_HEADER_FILE_WITH_PROPER_NAMES ${HEADER_FILE_NAME} IS_HEADER_FOUND)
331       endif()
332       
333       if (${IS_HEADER_FOUND} EQUAL -1)
334         message (STATUS "Warning. \(${PACKAGE_NAME}\) ${OCCT_HEADER_FILE_OLD} is not used and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
335         file (REMOVE "${OCCT_HEADER_FILE_OLD}")
336       endif()
337     endif()
338   endforeach()
339 endmacro()
340
341 macro (OCCT_COPY_FILE_OR_DIR BEING_COPIED_OBJECT DESTINATION_PATH)
342   # first of all, copy original files
343   if (EXISTS "${CMAKE_SOURCE_DIR}/${BEING_COPIED_OBJECT}")
344     file (COPY "${CMAKE_SOURCE_DIR}/${BEING_COPIED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
345   endif()
346
347   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_COPIED_OBJECT}")
348     # secondly, rewrite original files with patched ones
349     file (COPY "${BUILD_PATCH}/${BEING_COPIED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
350   endif()
351 endmacro()
352
353 macro (OCCT_CONFIGURE BEING_CONGIRUGED_FILE FINAL_NAME)
354   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_CONGIRUGED_FILE}")
355     configure_file("${BUILD_PATCH}/${BEING_CONGIRUGED_FILE}" "${FINAL_NAME}" @ONLY)
356   else()
357     configure_file("${CMAKE_SOURCE_DIR}/${BEING_CONGIRUGED_FILE}" "${FINAL_NAME}" @ONLY)
358   endif()
359 endmacro()
360
361 macro (OCCT_ADD_SUBDIRECTORY BEING_ADDED_DIRECTORY)
362   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_ADDED_DIRECTORY}/CMakeLists.txt")
363     add_subdirectory(${BUILD_PATCH}/${BEING_ADDED_DIRECTORY})
364   elseif (EXISTS "${CMAKE_SOURCE_DIR}/${BEING_ADDED_DIRECTORY}/CMakeLists.txt")
365     add_subdirectory (${CMAKE_SOURCE_DIR}/${BEING_ADDED_DIRECTORY})
366   else()
367     message (STATUS "${BEING_ADDED_DIRECTORY} directory is not included")
368   endif()
369 endmacro()
370
371 function (OCCT_IS_PRODUCT_REQUIRED CSF_VAR_NAME USE_PRODUCT)
372   set (${USE_PRODUCT} OFF PARENT_SCOPE)
373
374   if (NOT BUILD_TOOLKITS)
375     message(STATUS "Warning: the list of being used toolkits is empty")
376   else()
377     foreach (USED_TOOLKIT ${BUILD_TOOLKITS})
378       if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${USED_TOOLKIT}/EXTERNLIB")
379         file (READ "${BUILD_PATCH}/src/${USED_TOOLKIT}/EXTERNLIB" FILE_CONTENT)
380       elseif (EXISTS "${CMAKE_SOURCE_DIR}/src/${USED_TOOLKIT}/EXTERNLIB")
381         file (READ "${CMAKE_SOURCE_DIR}/src/${USED_TOOLKIT}/EXTERNLIB" FILE_CONTENT)
382       endif()
383
384       string (REGEX MATCH "${CSF_VAR_NAME}" DOES_FILE_CONTAIN "${FILE_CONTENT}")
385
386       if (DOES_FILE_CONTAIN)
387         set (${USE_PRODUCT} ON PARENT_SCOPE)
388         break()
389       endif()
390     endforeach()
391   endif()
392 endfunction()
393
394 function (FILE_TO_LIST FILE_NAME FILE_CONTENT)
395   set (LOCAL_FILE_CONTENT)
396   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${FILE_NAME}")
397     file (STRINGS "${BUILD_PATCH}/${FILE_NAME}" LOCAL_FILE_CONTENT)
398   elseif (EXISTS "${CMAKE_SOURCE_DIR}/${FILE_NAME}")
399     file (STRINGS "${CMAKE_SOURCE_DIR}/${FILE_NAME}" LOCAL_FILE_CONTENT)
400   endif()
401
402   set (${FILE_CONTENT} ${LOCAL_FILE_CONTENT} PARENT_SCOPE)
403 endfunction()
404
405 # Function to determine if TOOLKIT is OCCT toolkit
406 function (IS_OCCT_TOOLKIT TOOLKIT_NAME MODULES IS_TOOLKIT_FOUND)
407   set (${IS_TOOLKIT_FOUND} OFF PARENT_SCOPE)
408   foreach (MODULE ${${MODULES}})
409     set (TOOLKITS ${${MODULE}_TOOLKITS})
410     list (FIND TOOLKITS ${TOOLKIT_NAME} FOUND)
411
412     if (NOT ${FOUND} EQUAL -1)
413       set (${IS_TOOLKIT_FOUND} ON PARENT_SCOPE)
414     endif()
415   endforeach(MODULE)
416 endfunction()
417
418 # TOOLKIT_DEPS is defined with dependencies from file src/TOOLKIT_NAME/EXTERNLIB.
419 # CSF_ variables are ignored
420 function (OCCT_TOOLKIT_DEP TOOLKIT_NAME TOOLKIT_DEPS)
421   FILE_TO_LIST ("src/${TOOLKIT_NAME}/EXTERNLIB" FILE_CONTENT)
422
423   #list (APPEND LOCAL_TOOLKIT_DEPS ${TOOLKIT_NAME})
424   set (LOCAL_TOOLKIT_DEPS)
425   foreach (FILE_CONTENT_LINE ${FILE_CONTENT})
426     string (REGEX MATCH "^TK" TK_FOUND ${FILE_CONTENT_LINE})
427     if ("x${FILE_CONTENT_LINE}" STREQUAL "xDRAWEXE" OR NOT "${TK_FOUND}" STREQUAL "")
428       list (APPEND LOCAL_TOOLKIT_DEPS ${FILE_CONTENT_LINE})
429     endif()
430   endforeach()
431
432   set (${TOOLKIT_DEPS} ${LOCAL_TOOLKIT_DEPS} PARENT_SCOPE)
433 endfunction()
434
435 # TOOLKIT_FULL_DEPS is defined with complete dependencies (all levels)
436 function (OCCT_TOOLKIT_FULL_DEP TOOLKIT_NAME TOOLKIT_FULL_DEPS)
437   # first level dependencies are stored in LOCAL_TOOLKIT_FULL_DEPS
438   OCCT_TOOLKIT_DEP (${TOOLKIT_NAME} LOCAL_TOOLKIT_FULL_DEPS)
439
440   list (LENGTH LOCAL_TOOLKIT_FULL_DEPS LIST_LENGTH)
441   set (LIST_INDEX 0)
442   while (LIST_INDEX LESS LIST_LENGTH)
443     list (GET LOCAL_TOOLKIT_FULL_DEPS ${LIST_INDEX} CURRENT_TOOLKIT)
444     OCCT_TOOLKIT_DEP (${CURRENT_TOOLKIT} CURRENT_TOOLKIT_DEPS)
445
446     # append toolkits are not contained
447     foreach (CURRENT_TOOLKIT_DEP ${CURRENT_TOOLKIT_DEPS})
448       set (CURRENT_TOOLKIT_DEP_FOUND OFF)
449       foreach (LOCAL_TOOLKIT_FULL_DEP ${LOCAL_TOOLKIT_FULL_DEPS})
450         if ("${CURRENT_TOOLKIT_DEP}" STREQUAL "${LOCAL_TOOLKIT_FULL_DEP}")
451           set (CURRENT_TOOLKIT_DEP_FOUND ON)
452           break()
453         endif()
454       endforeach()
455       if ("${CURRENT_TOOLKIT_DEP_FOUND}" STREQUAL "OFF")
456         list (APPEND LOCAL_TOOLKIT_FULL_DEPS ${CURRENT_TOOLKIT_DEP})
457       endif()
458     endforeach()
459
460     # increment the list index
461     MATH(EXPR LIST_INDEX "${LIST_INDEX}+1")
462
463     # calculate new length
464     list (LENGTH LOCAL_TOOLKIT_FULL_DEPS LIST_LENGTH)
465   endwhile()
466
467   set (${TOOLKIT_FULL_DEPS} ${LOCAL_TOOLKIT_FULL_DEPS} PARENT_SCOPE)
468 endfunction()
469
470 # Function to get list of modules and toolkits from file adm/MODULES.
471 # Creates list <$MODULE_LIST> to store list of MODULES and
472 # <NAME_OF_MODULE>_TOOLKITS foreach module to store its toolkits.
473 function (OCCT_MODULES_AND_TOOLKITS MODULE_LIST)
474   FILE_TO_LIST ("adm/MODULES" FILE_CONTENT)
475
476   foreach (CONTENT_LINE ${FILE_CONTENT})
477     string (REPLACE " " ";" CONTENT_LINE ${CONTENT_LINE})
478     list (GET CONTENT_LINE 0 MODULE_NAME)
479     list (REMOVE_AT CONTENT_LINE 0)
480     list (APPEND ${MODULE_LIST} ${MODULE_NAME})
481     # (!) REMOVE THE LINE BELOW (implicit variables)
482     set (${MODULE_NAME}_TOOLKITS ${CONTENT_LINE} PARENT_SCOPE)
483   endforeach()
484
485   set (${MODULE_LIST} ${${MODULE_LIST}} PARENT_SCOPE)
486 endfunction()
487
488 # Returns OCC version string from file Standard_Version.hxx (if available)
489 function (OCC_VERSION OCC_VERSION_MAJOR OCC_VERSION_MINOR OCC_VERSION_MAINTENANCE OCC_VERSION_DEVELOPMENT OCC_VERSION_STRING_EXT)
490
491   set (OCC_VERSION_MAJOR         7)
492   set (OCC_VERSION_MINOR         0)
493   set (OCC_VERSION_MAINTENANCE   0)
494   set (OCC_VERSION_DEVELOPMENT   dev)
495   set (OCC_VERSION_COMPLETE      "7.0.0")
496  
497   set (STANDARD_VERSION_FILE "${CMAKE_SOURCE_DIR}/src/Standard/Standard_Version.hxx")
498   if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/Standard/Standard_Version.hxx")
499     set (STANDARD_VERSION_FILE "${BUILD_PATCH}/src/Standard/Standard_Version.hxx")
500   endif()
501
502   if (EXISTS "${STANDARD_VERSION_FILE}")
503     foreach (SOUGHT_VERSION OCC_VERSION_MAJOR OCC_VERSION_MINOR OCC_VERSION_MAINTENANCE)
504       file (STRINGS "${STANDARD_VERSION_FILE}" ${SOUGHT_VERSION} REGEX "^#define ${SOUGHT_VERSION} .*")
505       string (REGEX REPLACE ".*${SOUGHT_VERSION} .*([^ ]+).*" "\\1" ${SOUGHT_VERSION} "${${SOUGHT_VERSION}}" )
506     endforeach()
507     
508     foreach (SOUGHT_VERSION OCC_VERSION_DEVELOPMENT OCC_VERSION_COMPLETE)
509       file (STRINGS "${STANDARD_VERSION_FILE}" ${SOUGHT_VERSION} REGEX "^#define ${SOUGHT_VERSION} .*")
510       string (REGEX REPLACE ".*${SOUGHT_VERSION} .*\"([^ ]+)\".*" "\\1" ${SOUGHT_VERSION} "${${SOUGHT_VERSION}}" )
511     endforeach()
512   endif()
513  
514   set (OCC_VERSION_MAJOR "${OCC_VERSION_MAJOR}" PARENT_SCOPE)
515   set (OCC_VERSION_MINOR "${OCC_VERSION_MINOR}" PARENT_SCOPE)
516   set (OCC_VERSION_MAINTENANCE "${OCC_VERSION_MAINTENANCE}" PARENT_SCOPE)
517   set (OCC_VERSION_DEVELOPMENT "${OCC_VERSION_DEVELOPMENT}" PARENT_SCOPE)
518   
519   if (OCC_VERSION_DEVELOPMENT AND OCC_VERSION_COMPLETE)
520     set (OCC_VERSION_STRING_EXT "${OCC_VERSION_COMPLETE}.${OCC_VERSION_DEVELOPMENT}" PARENT_SCOPE)
521   else()
522     set (OCC_VERSION_STRING_EXT "${OCC_VERSION_COMPLETE}" PARENT_SCOPE)
523   endif()
524 endfunction()
525
526 macro (CHECK_PATH_FOR_CONSISTENCY THE_ROOT_PATH_NAME THE_BEING_CHECKED_PATH_NAME THE_VAR_TYPE THE_MESSAGE_OF_BEING_CHECKED_PATH)
527   
528   set (THE_ROOT_PATH "${${THE_ROOT_PATH_NAME}}")
529   set (THE_BEING_CHECKED_PATH "${${THE_BEING_CHECKED_PATH_NAME}}")
530
531   if (THE_BEING_CHECKED_PATH OR EXISTS "${THE_BEING_CHECKED_PATH}")
532     get_filename_component (THE_ROOT_PATH_ABS "${THE_ROOT_PATH}" ABSOLUTE)
533     get_filename_component (THE_BEING_CHECKED_PATH_ABS "${THE_BEING_CHECKED_PATH}" ABSOLUTE)
534
535     string (REGEX MATCH "${THE_ROOT_PATH_ABS}" DOES_PATH_CONTAIN "${THE_BEING_CHECKED_PATH_ABS}")
536
537     if (NOT DOES_PATH_CONTAIN) # if cmake found the being checked path at different place from THE_ROOT_PATH_ABS
538       set (${THE_BEING_CHECKED_PATH_NAME} "" CACHE ${THE_VAR_TYPE} "${THE_MESSAGE_OF_BEING_CHECKED_PATH}" FORCE)
539     endif()
540   else()
541     set (${THE_BEING_CHECKED_PATH_NAME} "" CACHE ${THE_VAR_TYPE} "${THE_MESSAGE_OF_BEING_CHECKED_PATH}" FORCE)
542   endif()
543
544 endmacro()
545
546 # Adds OCCT_INSTALL_BIN_LETTER variable ("" for Release, "d" for Debug and 
547 # "i" for RelWithDebInfo) in OpenCASCADETargets-*.cmake files during 
548 # installation process.
549 # This and the following macros are used to overcome limitation of CMake
550 # prior to version 3.3 not supporting per-configuration install paths
551 # for install target files (see https://cmake.org/Bug/view.php?id=14317)
552 macro (OCCT_UPDATE_TARGET_FILE)
553   if (NOT SINGLE_GENERATOR)
554     OCCT_INSERT_CODE_FOR_TARGET ()
555   endif()
556
557   install (CODE
558   "cmake_policy(PUSH)
559   cmake_policy(SET CMP0007 NEW)
560   string (TOLOWER \"\${CMAKE_INSTALL_CONFIG_NAME}\" CMAKE_INSTALL_CONFIG_NAME_LOWERCASE)
561   file (GLOB ALL_OCCT_TARGET_FILES \"${INSTALL_DIR}/${INSTALL_DIR_CMAKE}/OpenCASCADE*Targets-\${CMAKE_INSTALL_CONFIG_NAME_LOWERCASE}.cmake\")
562   foreach(TARGET_FILENAME \${ALL_OCCT_TARGET_FILES})
563     file (STRINGS \"\${TARGET_FILENAME}\" TARGET_FILE_CONTENT)
564     file (REMOVE \"\${TARGET_FILENAME}\")
565     foreach (line IN LISTS TARGET_FILE_CONTENT)
566       string (REGEX REPLACE \"[\\\\]?[\\\$]{OCCT_INSTALL_BIN_LETTER}\" \"\${OCCT_INSTALL_BIN_LETTER}\" line \"\${line}\")
567       file (APPEND \"\${TARGET_FILENAME}\" \"\${line}\\n\")
568     endforeach()
569   endforeach()
570   cmake_policy(POP)")
571 endmacro()
572
573 macro (OCCT_INSERT_CODE_FOR_TARGET)
574   install(CODE "if (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$\")
575     set (OCCT_INSTALL_BIN_LETTER \"\")
576   elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$\")
577     set (OCCT_INSTALL_BIN_LETTER \"i\")
578   elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
579     set (OCCT_INSTALL_BIN_LETTER \"d\")
580   endif()")
581 endmacro()
582
583 macro (OCCT_UPDATE_DRAW_DEFAULT_FILE)
584   install(CODE "cmake_policy(PUSH)
585   cmake_policy(SET CMP0007 NEW)
586   set (DRAW_DEFAULT_FILE_NAME \"${INSTALL_DIR}/${INSTALL_DIR_RESOURCE}/DrawResources/DrawPlugin\")
587   file (STRINGS \"\${DRAW_DEFAULT_FILE_NAME}\" DRAW_DEFAULT_CONTENT)
588   file (REMOVE \"\${DRAW_DEFAULT_FILE_NAME}\")
589   foreach (line IN LISTS DRAW_DEFAULT_CONTENT)
590     string (REGEX MATCH \": TK\([a-zA-Z]+\)$\" IS_TK_LINE \"\${line}\")
591     string (REGEX REPLACE \": TK\([a-zA-Z]+\)$\" \": TK\${CMAKE_MATCH_1}${BUILD_SHARED_LIBRARY_NAME_POSTFIX}\" line \"\${line}\")
592     file (APPEND \"\${DRAW_DEFAULT_FILE_NAME}\" \"\${line}\\n\")
593   endforeach()
594   cmake_policy(POP)")
595 endmacro()
596
597 macro (OCCT_CREATE_SYMLINK_TO_FILE LIBRARY_NAME LINK_NAME)
598   if (NOT WIN32)
599     install (CODE "if (EXISTS \"${LIBRARY_NAME}\")
600         execute_process (COMMAND ln -s \"${LIBRARY_NAME}\" \"${LINK_NAME}\")
601       endif()
602     ")
603   endif()
604 endmacro()