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