0026865: Configuration, CMake - ensure consistency between FILES and actual content...
[occt.git] / adm / cmake / occt_macros.cmake
1 #
2 macro (OCCT_CHECK_AND_UNSET VARNAME)
3   if (DEFINED ${VARNAME})
4     unset (${VARNAME} CACHE)
5   endif()
6 endmacro()
7
8 macro (OCCT_CHECK_AND_UNSET_GROUP VARNAME)
9   OCCT_CHECK_AND_UNSET ("${VARNAME}_DIR")
10
11   OCCT_CHECK_AND_UNSET ("${VARNAME}_INCLUDE_DIR")
12
13   OCCT_CHECK_AND_UNSET ("${VARNAME}_LIBRARY")
14   OCCT_CHECK_AND_UNSET ("${VARNAME}_LIBRARY_DIR")
15
16   if (WIN32)
17     OCCT_CHECK_AND_UNSET ("${VARNAME}_DLL")
18     OCCT_CHECK_AND_UNSET ("${VARNAME}_DLL_DIR")
19   endif()
20 endmacro()
21
22 # COMPILER_BITNESS variable
23 macro (OCCT_MAKE_COMPILER_BITNESS)
24   math (EXPR COMPILER_BITNESS "32 + 32*(${CMAKE_SIZEOF_VOID_P}/8)")
25 endmacro()
26
27 # OS_WITH_BIT
28 macro (OCCT_MAKE_OS_WITH_BITNESS)
29
30   OCCT_MAKE_COMPILER_BITNESS()
31
32   if (WIN32)
33     set (OS_WITH_BIT "win${COMPILER_BITNESS}")
34   elseif(APPLE)
35     set (OS_WITH_BIT "mac${COMPILER_BITNESS}")
36   else()
37     set (OS_WITH_BIT "lin${COMPILER_BITNESS}")
38   endif()
39 endmacro()
40
41 # COMPILER variable
42 macro (OCCT_MAKE_COMPILER_SHORT_NAME)
43   if (MSVC)
44     if (MSVC70)
45       set (COMPILER vc7)
46     elseif (MSVC80)
47       set (COMPILER vc8)
48     elseif (MSVC90)
49       set (COMPILER vc9)
50     elseif (MSVC10)
51       set (COMPILER vc10)
52     elseif (MSVC11)
53       set (COMPILER vc11)
54     elseif (MSVC12)
55       set (COMPILER vc12)
56     elseif (MSVC14)
57       set (COMPILER vc14)
58     endif()
59   elseif (DEFINED CMAKE_COMPILER_IS_GNUCC)
60     set (COMPILER gcc)
61   elseif (DEFINED CMAKE_COMPILER_IS_GNUCXX)
62     set (COMPILER gxx)
63   elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
64     set (COMPILER clang)
65   elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
66     set (COMPILER icc)
67   else()
68     set (COMPILER ${CMAKE_GENERATOR})
69     string (REGEX REPLACE " " "" COMPILER ${COMPILER})
70   endif()
71 endmacro()
72
73 function (SUBDIRECTORY_NAMES MAIN_DIRECTORY RESULT)
74   file (GLOB SUB_ITEMS "${MAIN_DIRECTORY}/*")
75
76   foreach (ITEM ${SUB_ITEMS})
77     if (IS_DIRECTORY "${ITEM}")
78       get_filename_component (ITEM_NAME "${ITEM}" NAME)
79       list (APPEND LOCAL_RESULT "${ITEM_NAME}")
80     endif()
81   endforeach()
82   set (${RESULT} ${LOCAL_RESULT} PARENT_SCOPE)
83 endfunction()
84
85 function (OCCT_ORIGIN_AND_PATCHED_FILES RELATIVE_PATH SEARCH_TEMPLATE RESULT)
86
87   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${RELATIVE_PATH}")
88     file (GLOB FOUND_FILES "${APPLY_OCCT_PATCH_DIR}/${RELATIVE_PATH}/${SEARCH_TEMPLATE}")
89   endif()
90
91   file (GLOB ORIGIN_FILES "${CMAKE_SOURCE_DIR}/${RELATIVE_PATH}/${SEARCH_TEMPLATE}")
92   foreach (ORIGIN_FILE ${ORIGIN_FILES})
93     # check for existence of patched version of current file
94     if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${RELATIVE_PATH}")
95       get_filename_component (ORIGIN_FILE_NAME "${ORIGIN_FILE}" NAME)
96       if (EXISTS "${APPLY_OCCT_PATCH_DIR}/${RELATIVE_PATH}/${ORIGIN_FILE_NAME}")
97         continue()
98       endif()
99     endif()
100
101     # append origin version if patched one is not found
102     list (APPEND FOUND_FILES ${ORIGIN_FILE})
103   endforeach()
104
105   set (${RESULT} ${FOUND_FILES} PARENT_SCOPE)
106 endfunction()
107
108 function (FIND_PRODUCT_DIR ROOT_DIR PRODUCT_NAME RESULT)
109   OCCT_MAKE_COMPILER_SHORT_NAME()
110   OCCT_MAKE_COMPILER_BITNESS()
111
112   string (TOLOWER "${PRODUCT_NAME}" lower_PRODUCT_NAME)
113
114   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*${COMPILER}.*${COMPILER_BITNESS}")
115   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*[0-9.]+.*${COMPILER}.*${COMPILER_BITNESS}")
116   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*[0-9.]+.*${COMPILER_BITNESS}")
117   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*[0-9.]+")
118   list (APPEND SEARCH_TEMPLATES "^[^a-zA-Z]*${lower_PRODUCT_NAME}[^a-zA-Z]*")
119
120   SUBDIRECTORY_NAMES ("${ROOT_DIR}" SUBDIR_NAME_LIST)
121
122   foreach (SEARCH_TEMPLATE ${SEARCH_TEMPLATES})
123     if (LOCAL_RESULT)
124       BREAK()
125     endif()
126
127     foreach (SUBDIR_NAME ${SUBDIR_NAME_LIST})
128       string (TOLOWER "${SUBDIR_NAME}" lower_SUBDIR_NAME)
129
130       string (REGEX MATCH "${SEARCH_TEMPLATE}" DUMMY_VAR "${lower_SUBDIR_NAME}")
131       if (DUMMY_VAR)
132         list (APPEND LOCAL_RESULT ${SUBDIR_NAME})
133       endif()
134     endforeach()
135   endforeach()
136
137   if (LOCAL_RESULT)
138     list (LENGTH "${LOCAL_RESULT}" LOC_LEN)
139     math (EXPR LAST_ELEMENT_INDEX "${LOC_LEN}-1")
140     list (GET LOCAL_RESULT ${LAST_ELEMENT_INDEX} DUMMY)
141     set (${RESULT} ${DUMMY} PARENT_SCOPE)
142   endif()
143 endfunction()
144
145 macro (OCCT_INSTALL_FILE_OR_DIR BEING_INSTALLED_OBJECT DESTINATION_PATH)
146   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${BEING_INSTALLED_OBJECT}")
147     if (IS_DIRECTORY "${APPLY_OCCT_PATCH_DIR}/${BEING_INSTALLED_OBJECT}")
148       # first of all, install original files
149       install (DIRECTORY "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
150
151       # secondly, rewrite original files with patched ones
152       install (DIRECTORY "${APPLY_OCCT_PATCH_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
153     else()
154       install (FILES     "${APPLY_OCCT_PATCH_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
155     endif()
156   else()
157     if (IS_DIRECTORY "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}")
158       install (DIRECTORY "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
159     else()
160       install (FILES     "${CMAKE_SOURCE_DIR}/${BEING_INSTALLED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
161     endif()
162   endif()
163 endmacro()
164
165 macro (OCCT_CONFIGURE_AND_INSTALL BEING_CONGIRUGED_FILE BUILD_NAME INSTALL_NAME DESTINATION_PATH)
166   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${BEING_CONGIRUGED_FILE}")
167     configure_file("${APPLY_OCCT_PATCH_DIR}/${BEING_CONGIRUGED_FILE}" "${BUILD_NAME}" @ONLY)
168   else()
169     configure_file("${CMAKE_SOURCE_DIR}/${BEING_CONGIRUGED_FILE}" "${BUILD_NAME}" @ONLY)
170   endif()
171
172   install(FILES "${OCCT_BINARY_DIR}/${BUILD_NAME}" DESTINATION  "${DESTINATION_PATH}" RENAME ${INSTALL_NAME})
173 endmacro()
174
175 macro (COLLECT_AND_INSTALL_OCCT_HEADER_FILES ROOT_TARGET_OCCT_DIR OCCT_BUILD_TOOLKITS)
176   set (OCCT_USED_PACKAGES)
177
178   # consider patched header.in template
179   set (TEMPLATE_HEADER_PATH "${CMAKE_SOURCE_DIR}/adm/templates/header.in")
180   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/adm/templates/header.in")
181     set (TEMPLATE_HEADER_PATH "${APPLY_OCCT_PATCH_DIR}/adm/templates/header.in")
182   endif()
183
184   set (ROOT_OCCT_DIR ${CMAKE_SOURCE_DIR})
185
186   foreach (OCCT_USED_TOOLKIT ${OCCT_BUILD_TOOLKITS})
187     # append all required package folders
188     set (OCCT_TOOLKIT_PACKAGES)
189     if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/src/${OCCT_USED_TOOLKIT}/PACKAGES")
190       file (STRINGS "${APPLY_OCCT_PATCH_DIR}/src/${OCCT_USED_TOOLKIT}/PACKAGES" OCCT_TOOLKIT_PACKAGES)
191     elseif (EXISTS "${CMAKE_SOURCE_DIR}/src/${OCCT_USED_TOOLKIT}/PACKAGES")
192       file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_USED_TOOLKIT}/PACKAGES" OCCT_TOOLKIT_PACKAGES)
193     endif()
194
195     list (APPEND OCCT_USED_PACKAGES ${OCCT_TOOLKIT_PACKAGES})
196   endforeach()
197
198   list (REMOVE_DUPLICATES OCCT_USED_PACKAGES)
199
200   set (OCCT_HEADER_FILES_COMPLETE)
201   set (OCCT_HEADER_FILE_NAMES_NOT_IN_FILES)
202   set (OCCT_HEADER_FILE_WITH_PROPER_NAMES)
203   foreach (OCCT_PACKAGE ${OCCT_USED_PACKAGES})
204     if (NOT EXISTS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES")
205       message (WARNING "FILES has not been found in ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}")
206       continue()
207     endif()
208
209     file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" OCCT_ALL_FILE_NAMES)
210
211     # emit warnings if there is unprocessed headers
212     file (GLOB OCCT_ALL_FILES_IN_DIR "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/*.*")
213     foreach (OCCT_FILE_IN_DIR ${OCCT_ALL_FILES_IN_DIR})
214       foreach (OCCT_FILE_NAME ${OCCT_ALL_FILE_NAMES})
215         string (REGEX MATCH "${OCCT_FILE_NAME}" IS_FILE_FOUND "${OCCT_FILE_IN_DIR}")
216         if (IS_FILE_FOUND)
217           string (REGEX MATCH ".+[.]h|[lg]xx" IS_HEADER_FOUND "${OCCT_FILE_NAME}")
218           if (IS_HEADER_FOUND)
219             list (APPEND OCCT_HEADER_FILES_COMPLETE ${OCCT_HEADER_FILE_IN_DIR})
220
221             # collect header files with name that does not contain its package one
222             string (FIND "${OCCT_FILE_NAME}" "${OCCT_PACKAGE}_" FOUND_INDEX)
223             if (NOT ${FOUND_INDEX} EQUAL 0)
224               list (APPEND OCCT_HEADER_FILE_WITH_PROPER_NAMES "${OCCT_FILE_NAME}")
225             endif()            
226           endif()
227
228           break()
229         endif()
230       endforeach()
231
232       if (NOT IS_FILE_FOUND)
233         message (STATUS "Warning. ${OCCT_FILE_IN_DIR} is not involved into ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES")
234         
235         string (REGEX MATCH ".+[.]h|[lg]xx" IS_HEADER_FOUND "${OCCT_FILE_NAME}")
236         if (IS_HEADER_FOUND)
237           list (APPEND OCCT_HEADER_FILE_NAMES_NOT_IN_FILES ${OCCT_FILE_NAME})
238         endif()
239       endif()
240     endforeach()
241   endforeach()
242   
243   # create new file including found header
244   foreach (OCCT_HEADER_FILE ${OCCT_HEADER_FILES_COMPLETE})
245     get_filename_component (HEADER_FILE_NAME ${OCCT_HEADER_FILE} NAME)
246     configure_file ("${TEMPLATE_HEADER_PATH}" "${ROOT_TARGET_OCCT_DIR}/inc/${HEADER_FILE_NAME}" @ONLY)
247   endforeach()
248   
249   install (FILES ${OCCT_HEADER_FILES_COMPLETE} DESTINATION "${INSTALL_DIR}/inc")
250   
251   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
252   message (STATUS "Info. \(${CURRENT_TIME}\) Checking headers in inc folder...")
253     
254   file (GLOB OCCT_HEADER_FILES_OLD "${ROOT_TARGET_OCCT_DIR}/inc/*")
255   foreach (OCCT_HEADER_FILE_OLD ${OCCT_HEADER_FILES_OLD})
256     get_filename_component (HEADER_FILE_NAME ${OCCT_HEADER_FILE_OLD} NAME)
257     string (REGEX MATCH "^[a-zA-Z0-9]+" PACKAGE_NAME "${HEADER_FILE_NAME}")
258     
259     list (FIND OCCT_USED_PACKAGES ${PACKAGE_NAME} IS_HEADER_FOUND)
260     if (NOT ${IS_HEADER_FOUND} EQUAL -1)
261       if (NOT EXISTS "${CMAKE_SOURCE_DIR}/src/${PACKAGE_NAME}/${HEADER_FILE_NAME}")
262         message (STATUS "Warning. ${OCCT_HEADER_FILE_OLD} is not presented in the sources and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
263         file (REMOVE "${OCCT_HEADER_FILE_OLD}")
264       else()
265         list (FIND OCCT_HEADER_FILE_NAMES_NOT_IN_FILES ${PACKAGE_NAME} IS_HEADER_FOUND)
266         if (NOT ${IS_HEADER_FOUND} EQUAL -1)
267           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")
268           file (REMOVE "${OCCT_HEADER_FILE_OLD}")
269         endif()
270       endif()
271     else()
272       set (IS_HEADER_FOUND -1)
273       if (NOT "${OCCT_HEADER_FILE_WITH_PROPER_NAMES}" STREQUAL "")
274         list (FIND OCCT_HEADER_FILE_WITH_PROPER_NAMES ${HEADER_FILE_NAME} IS_HEADER_FOUND)
275       endif()
276       
277       if (${IS_HEADER_FOUND} EQUAL -1)
278         message (STATUS "Warning. \(${PACKAGE_NAME}\) ${OCCT_HEADER_FILE_OLD} is not used and will be removed from ${ROOT_TARGET_OCCT_DIR}/inc")
279         file (REMOVE "${OCCT_HEADER_FILE_OLD}")
280       endif()
281     endif()
282   endforeach()
283   
284   string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
285   message (STATUS "Info. \(${CURRENT_TIME}\) End the checking")
286
287 endmacro()
288
289 macro (OCCT_COPY_FILE_OR_DIR BEING_COPIED_OBJECT DESTINATION_PATH)
290   # first of all, copy original files
291   if (EXISTS "${CMAKE_SOURCE_DIR}/${BEING_COPIED_OBJECT}")
292     file (COPY "${CMAKE_SOURCE_DIR}/${BEING_COPIED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
293   endif()
294
295   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${BEING_COPIED_OBJECT}")
296     # secondly, rewrite original files with patched ones
297     file (COPY "${APPLY_OCCT_PATCH_DIR}/${BEING_COPIED_OBJECT}" DESTINATION  "${DESTINATION_PATH}")
298   endif()
299 endmacro()
300
301 macro (OCCT_CONFIGURE BEING_CONGIRUGED_FILE FINAL_NAME)
302   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${BEING_CONGIRUGED_FILE}")
303     configure_file("${APPLY_OCCT_PATCH_DIR}/${BEING_CONGIRUGED_FILE}" "${FINAL_NAME}" @ONLY)
304   else()
305     configure_file("${CMAKE_SOURCE_DIR}/${BEING_CONGIRUGED_FILE}" "${FINAL_NAME}" @ONLY)
306   endif()
307 endmacro()
308
309 macro (OCCT_ADD_SUBDIRECTORY BEING_ADDED_DIRECTORY)
310   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${BEING_ADDED_DIRECTORY}/CMakeLists.txt")
311     add_subdirectory(${APPLY_OCCT_PATCH_DIR}/${BEING_ADDED_DIRECTORY})
312   elseif (EXISTS "${CMAKE_SOURCE_DIR}/${BEING_ADDED_DIRECTORY}/CMakeLists.txt")
313     add_subdirectory (${CMAKE_SOURCE_DIR}/${BEING_ADDED_DIRECTORY})
314   else()
315     message (STATUS "${BEING_ADDED_DIRECTORY} directory is not included")
316   endif()
317 endmacro()
318
319 function (OCCT_IS_PRODUCT_REQUIRED CSF_VAR_NAME USE_PRODUCT)
320   set (${USE_PRODUCT} OFF PARENT_SCOPE)
321
322   if (NOT BUILD_TOOLKITS)
323     message(STATUS "Warning: the list of being used toolkits is empty")
324   else()
325     foreach (USED_TOOLKIT ${BUILD_TOOLKITS})
326       if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/src/${USED_TOOLKIT}/EXTERNLIB")
327         file (READ "${APPLY_OCCT_PATCH_DIR}/src/${USED_TOOLKIT}/EXTERNLIB" FILE_CONTENT)
328       elseif (EXISTS "${CMAKE_SOURCE_DIR}/src/${USED_TOOLKIT}/EXTERNLIB")
329         file (READ "${CMAKE_SOURCE_DIR}/src/${USED_TOOLKIT}/EXTERNLIB" FILE_CONTENT)
330       endif()
331
332       string (REGEX MATCH "${CSF_VAR_NAME}" DOES_FILE_CONTAIN "${FILE_CONTENT}")
333
334       if (DOES_FILE_CONTAIN)
335         set (${USE_PRODUCT} ON PARENT_SCOPE)
336         break()
337       endif()
338     endforeach()
339   endif()
340 endfunction()
341
342 function (FILE_TO_LIST FILE_NAME FILE_CONTENT)
343   set (LOCAL_FILE_CONTENT)
344   if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/${FILE_NAME}")
345     file (STRINGS "${APPLY_OCCT_PATCH_DIR}/${FILE_NAME}" LOCAL_FILE_CONTENT)
346   elseif (EXISTS "${CMAKE_SOURCE_DIR}/${FILE_NAME}")
347     file (STRINGS "${CMAKE_SOURCE_DIR}/${FILE_NAME}" LOCAL_FILE_CONTENT)
348   endif()
349
350   set (${FILE_CONTENT} ${LOCAL_FILE_CONTENT} PARENT_SCOPE)
351 endfunction()
352
353 # Function to determine if TOOLKIT is OCCT toolkit
354 function (IS_OCCT_TOOLKIT TOOLKIT_NAME MODULES IS_TOOLKIT_FOUND)
355   set (${IS_TOOLKIT_FOUND} OFF PARENT_SCOPE)
356   foreach (MODULE ${${MODULES}})
357     set (TOOLKITS ${${MODULE}_TOOLKITS})
358     list (FIND TOOLKITS ${TOOLKIT_NAME} FOUND)
359
360     if (NOT ${FOUND} EQUAL -1)
361       set (${IS_TOOLKIT_FOUND} ON PARENT_SCOPE)
362     endif()
363   endforeach(MODULE)
364 endfunction()
365
366 # TOOLKIT_DEPS is defined with dependencies from file src/TOOLKIT_NAME/EXTERNLIB.
367 # CSF_ variables are ignored
368 function (OCCT_TOOLKIT_DEP TOOLKIT_NAME TOOLKIT_DEPS)
369   FILE_TO_LIST ("src/${TOOLKIT_NAME}/EXTERNLIB" FILE_CONTENT)
370
371   #list (APPEND LOCAL_TOOLKIT_DEPS ${TOOLKIT_NAME})
372   set (LOCAL_TOOLKIT_DEPS)
373   foreach (FILE_CONTENT_LINE ${FILE_CONTENT})
374     string (REGEX MATCH "^TK" TK_FOUND ${FILE_CONTENT_LINE})
375     if ("${FILE_CONTENT_LINE}" STREQUAL "DRAWEXE" OR NOT "${TK_FOUND}" STREQUAL "")
376       list (APPEND LOCAL_TOOLKIT_DEPS ${FILE_CONTENT_LINE})
377     endif()
378   endforeach()
379
380   set (${TOOLKIT_DEPS} ${LOCAL_TOOLKIT_DEPS} PARENT_SCOPE)
381 endfunction()
382
383 # TOOLKIT_FULL_DEPS is defined with complete dependencies (all levels)
384 function (OCCT_TOOLKIT_FULL_DEP TOOLKIT_NAME TOOLKIT_FULL_DEPS)
385   # first level dependencies are stored in LOCAL_TOOLKIT_FULL_DEPS
386   OCCT_TOOLKIT_DEP (${TOOLKIT_NAME} LOCAL_TOOLKIT_FULL_DEPS)
387
388   list (LENGTH LOCAL_TOOLKIT_FULL_DEPS LIST_LENGTH)
389   set (LIST_INDEX 0)
390   while (LIST_INDEX LESS LIST_LENGTH)
391     list (GET LOCAL_TOOLKIT_FULL_DEPS ${LIST_INDEX} CURRENT_TOOLKIT)
392     OCCT_TOOLKIT_DEP (${CURRENT_TOOLKIT} CURRENT_TOOLKIT_DEPS)
393
394     # append toolkits are not contained
395     foreach (CURRENT_TOOLKIT_DEP ${CURRENT_TOOLKIT_DEPS})
396       set (CURRENT_TOOLKIT_DEP_FOUND OFF)
397       foreach (LOCAL_TOOLKIT_FULL_DEP ${LOCAL_TOOLKIT_FULL_DEPS})
398         if ("${CURRENT_TOOLKIT_DEP}" STREQUAL "${LOCAL_TOOLKIT_FULL_DEP}")
399           set (CURRENT_TOOLKIT_DEP_FOUND ON)
400           break()
401         endif()
402       endforeach()
403       if ("${CURRENT_TOOLKIT_DEP_FOUND}" STREQUAL "OFF")
404         list (APPEND LOCAL_TOOLKIT_FULL_DEPS ${CURRENT_TOOLKIT_DEP})
405       endif()
406     endforeach()
407
408     # increment the list index
409     MATH(EXPR LIST_INDEX "${LIST_INDEX}+1")
410
411     # calculate new length
412     list (LENGTH LOCAL_TOOLKIT_FULL_DEPS LIST_LENGTH)
413   endwhile()
414
415   set (${TOOLKIT_FULL_DEPS} ${LOCAL_TOOLKIT_FULL_DEPS} PARENT_SCOPE)
416 endfunction()
417
418 # Function to get list of modules and toolkits from file adm/MODULES.
419 # Creates list <$MODULE_LIST> to store list of MODULES and
420 # <NAME_OF_MODULE>_TOOLKITS foreach module to store its toolkits.
421 function (OCCT_MODULES_AND_TOOLKITS MODULE_LIST)
422   FILE_TO_LIST ("adm/MODULES" FILE_CONTENT)
423
424   foreach (CONTENT_LINE ${FILE_CONTENT})
425     string (REPLACE " " ";" CONTENT_LINE ${CONTENT_LINE})
426     list (GET CONTENT_LINE 0 MODULE_NAME)
427     list (REMOVE_AT CONTENT_LINE 0)
428     list (APPEND ${MODULE_LIST} ${MODULE_NAME})
429     # (!) REMOVE THE LINE BELOW (implicit variables)
430     set (${MODULE_NAME}_TOOLKITS ${CONTENT_LINE} PARENT_SCOPE)
431   endforeach()
432
433   set (${MODULE_LIST} ${${MODULE_LIST}} PARENT_SCOPE)
434 endfunction()
435
436 # Returns OCCT version string from file Standard_Version.hxx (if available)
437 function (OCCT_VERSION OCCT_VERSION_VAR)
438   set (OCC_VERSION_COMPLETE "7.1.0")
439   set (OCC_VERSION_DEVELOPMENT "")
440   
441   set (OCCT_VERSION_LOCALVAR "${OCC_VERSION_COMPLETE}.${OCC_VERSION_DEVELOPMENT}")
442
443   set (STANDARD_VERSION_FILE "${CMAKE_SOURCE_DIR}/src/Standard/Standard_Version.hxx")
444   if (EXISTS "${STANDARD_VERSION_FILE}")
445     foreach (SOUGHT_VERSION OCC_VERSION_COMPLETE OCC_VERSION_DEVELOPMENT)
446       file (STRINGS "${STANDARD_VERSION_FILE}" ${SOUGHT_VERSION} REGEX "^#define ${SOUGHT_VERSION} .*")
447       string (REGEX REPLACE ".*${SOUGHT_VERSION} .*\"([^ ]+)\".*" "\\1" ${SOUGHT_VERSION} "${${SOUGHT_VERSION}}" )
448     endforeach()
449     
450     if (NOT "${OCC_VERSION_DEVELOPMENT}" STREQUAL "")
451       set (OCCT_VERSION_LOCALVAR "${OCC_VERSION_COMPLETE}.${OCC_VERSION_DEVELOPMENT}")
452     else()
453       set (OCCT_VERSION_LOCALVAR "${OCC_VERSION_COMPLETE}")
454     endif()
455   endif()
456
457   set (${OCCT_VERSION_VAR} "${OCCT_VERSION_LOCALVAR}" PARENT_SCOPE)
458 endfunction()
459