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