NiceModules.cmake 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. ####################################################################################
  2. # Help function for building the NICE library and its sub-libraries.
  3. # Inspired by the OpenCV cmake build system.
  4. #
  5. # Author: Johannes Ruehle
  6. # Date: 2014-02-17
  7. #
  8. ####################################################################################
  9. # get a list of all sub directories in curdir
  10. MACRO(SUBDIRLIST result curdir)
  11. FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
  12. SET(dirlist "")
  13. FOREACH(child ${children})
  14. IF(IS_DIRECTORY ${curdir}/${child})
  15. SET(dirlist ${dirlist} ${child})
  16. ENDIF()
  17. ENDFOREACH()
  18. SET(${result} ${dirlist})
  19. ENDMACRO()
  20. # get a list of all sub directories in curdir (recursive)
  21. # this function lists only the directories that contain relevant files
  22. MACRO(SUBDIRREC result curdir)
  23. FILE(GLOB_RECURSE children RELATIVE ${curdir} ${curdir}/*.c ${curdir}/*.cpp ${curdir}/*.h ${curdir}/*.tcc ${curdir}/Makefile)
  24. SET(dirlist "")
  25. FOREACH(child ${children})
  26. #message(STATUS ${child})
  27. GET_FILENAME_COMPONENT(to_add ${curdir}/${child} PATH)
  28. FILE(RELATIVE_PATH to_add_rel ${curdir} ${to_add})
  29. IF(IS_DIRECTORY ${curdir}/${to_add_rel})
  30. SET(dirlist ${dirlist} ${to_add_rel})
  31. ENDIF()
  32. ENDFOREACH()
  33. IF(NOT "${dirlist}" MATCHES "")
  34. LIST(REMOVE_DUPLICATES dirlist)
  35. ENDIF()
  36. SET(${result} ${dirlist})
  37. ENDMACRO()
  38. # update internal and external dependencies
  39. #
  40. # ${internal_deps} contains all the folders that are
  41. # "allowed". files in folders that are not part of this list will
  42. # _NOT_ be built.
  43. # the relevant libdepend.inc files are parsed until no more changes
  44. # are made
  45. macro(UPDATE_NICE_DEPENDENCIES)
  46. set(update_dependencies ON)
  47. while(update_dependencies)
  48. message(STATUS "updating dependencies...")
  49. set(update_dependencies OFF)
  50. set(remove_these "")
  51. foreach(_curDep ${internal_deps})
  52. nice_get_real_path(_curDepPath ${NICE_CURR_DIR}/${_curDep})
  53. if(EXISTS ${_curDepPath}/libdepend.inc)
  54. #message(STATUS "Reading dependencies for ${_curDep}...")
  55. file(STRINGS ${_curDepPath}/libdepend.inc _dependencies REGEX "^[$][(]call( )+PKG_DEPEND_INT,")
  56. file(STRINGS ${_curDepPath}/libdepend.inc _extdependencies REGEX "^[$][(]call( )+PKG_DEPEND_EXT,")
  57. #message(STATUS "Deps: ${_dependencies}")
  58. #message(STATUS "Deps: ${_extdependencies}")
  59. list(LENGTH _dependencies _depCount)
  60. if(${_depCount} GREATER 0)
  61. foreach(_innerDep ${_dependencies})
  62. string(REGEX REPLACE "^[$][(]call( )+PKG_DEPEND_INT,(.*)[)].*$" "\\2" _innerDepName "${_innerDep}")
  63. string(REGEX REPLACE "(.*)/$" "\\1" _innerDepName ${_innerDepName})
  64. #message(STATUS "Inner dep: ${_innerDepName} (command: ${_innerDep})")
  65. list(FIND internal_deps "${_innerDepName}" _innerDepFound)
  66. if(${_innerDepFound} LESS 0)
  67. message(STATUS "Removing ${_curDep} from build because ${_innerDepName} is missing")
  68. set(remove_these ${remove_these} ${_curDep})
  69. set(update_dependencies ON)
  70. endif()
  71. endforeach()
  72. endif()
  73. list(LENGTH _extdependencies _extdepCount)
  74. if(${_extdepCount} GREATER 0)
  75. foreach(_extDep ${_extdependencies})
  76. string(REGEX REPLACE "^[$][(]call( )+PKG_DEPEND_EXT,(.*)[)].*$" "\\2" _extDepName "${_extDep}")
  77. string(REGEX REPLACE "(.*)/$" "\\1" _extDepName ${_extDepName})
  78. #message(STATUS "External dep: ${_extDepName} (command: ${_extDep})")
  79. list(FIND external_deps "${_extDepName}" _extDepFound)
  80. if(${_extDepFound} LESS 0)
  81. message(STATUS "Removing ${_curDep} from build because ${_extDepName} (external) is missing")
  82. set(remove_these ${remove_these} ${_curDep})
  83. set(update_dependencies ON)
  84. endif()
  85. endforeach()
  86. endif()
  87. endif()
  88. endforeach()
  89. foreach(_toRemove ${remove_these})
  90. message(STATUS "Checking subdirectories for ${_toRemove}")
  91. foreach(_checkDep ${internal_deps})
  92. if(${_checkDep} MATCHES "^${_toRemove}.*$")
  93. message(STATUS "Removing ${_checkDep}...")
  94. LIST(REMOVE_ITEM internal_deps ${_checkDep})
  95. endif()
  96. endforeach()
  97. endforeach()
  98. endwhile()
  99. message(STATUS "Done.")
  100. endmacro()
  101. # get absolute path with symlinks resolved
  102. macro(nice_get_real_path VAR PATHSTR)
  103. if(CMAKE_VERSION VERSION_LESS 2.8)
  104. get_filename_component(${VAR} "${PATHSTR}" ABSOLUTE)
  105. else()
  106. get_filename_component(${VAR} "${PATHSTR}" REALPATH)
  107. endif()
  108. endmacro()
  109. # get the source files and store them in the variables:
  110. # ${nice_${the_library}_TESTFILES_SRC} (unit test cpps)
  111. # ${nice_${the_library}_PROGFILES_SRC} (progs cpps)
  112. # ${nice_${the_library}_SRC} (library cpp and tcc excluding progs and unit test cpps)
  113. # ${nice_${the_library}_HDR} (all library header files)
  114. #
  115. # Two methods for obtaining the source files:
  116. # 1) recursively scan all subdirectories
  117. # cmake variable NICE_SOURCEFILES_FIND_GLOBALLYRECURSIVE has to be set and to be true (1).
  118. # Notes:
  119. # - To exclude certain source files from appending in the source var, use the file black listing
  120. # in a file "list_exclude_from_build.cmake" by adding it to the variable "list_exclude_from_build_SRC"
  121. # in that file.
  122. # - All *moc_* files will be removed from the source file list variables
  123. # 2) use the given *.cmake files that define variables containing the source and header files to be used for build:
  124. # corefiles.cmake (Source files for Library build)
  125. # progfiles.cmake (source files for progam builds)
  126. # testfiles.cmake (source files for unit test builds)
  127. #
  128. #
  129. #Note: Variable ${the_library} contains the current (sub-)library name that called this function,
  130. # e.g. ${the_library} == 'core', ${the_library}=='vislearning'
  131. #
  132. # Author: Johannes Ruehle
  133. # Date: 2014-02-17
  134. #
  135. macro(nice_get_source_files)
  136. if(NICE_SOURCEFILES_FIND_GLOBALLYRECURSIVE)
  137. message(STATUS "Recursively scanning for source files")
  138. #include local file containing a list of files to be excluded from compilation
  139. #list is in variable list_exclude_from_build_SRC
  140. if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/list_exclude_from_build.cmake")
  141. #message(STATUS "exclude list found")
  142. include(list_exclude_from_build.cmake)
  143. message(STATUS "exclude list:${list_exclude_from_build_SRC}")
  144. endif()
  145. ### Get all unit test cpp files recursively
  146. set(nice_${the_library}_TESTFILES_SRC "")
  147. set(nice_${the_library}_PROGFILES_SRC "")
  148. set(nice_${the_library}_MEXFILES_SRC "")
  149. set(nice_${the_library}_SRC"")
  150. #message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
  151. file(GLOB_RECURSE list_tmp1 RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.cpp *.tcc *.c *.C)
  152. #message(STATUS "list_tmp1: ${list_tmp1}")
  153. foreach( t_SrcFile ${list_tmp1})
  154. get_filename_component(t_SrcPath ${t_SrcFile} PATH)
  155. set(t_SrcPath ${the_library}/${t_SrcPath})
  156. string(REGEX REPLACE "(.*)/+$" "\\1" t_SrcPath ${t_SrcPath})
  157. list(FIND internal_deps ${t_SrcPath} dep_index)
  158. if(NOT ${dep_index} LESS 0)
  159. if( NOT t_SrcFile MATCHES "moc_" )
  160. if( t_SrcFile MATCHES "tests/" )
  161. #message(STATUS "test: ${t_SrcFile}")
  162. LIST(APPEND nice_${the_library}_TESTFILES_SRC ${t_SrcFile})
  163. elseif( t_SrcFile MATCHES "progs/" )
  164. #message(STATUS "prog: ${t_SrcFile}")
  165. LIST(APPEND nice_${the_library}_PROGFILES_SRC ${t_SrcFile})
  166. elseif( t_SrcFile MATCHES "Mex[.]" )
  167. message(STATUS "mex: ${t_SrcFile}")
  168. LIST(APPEND nice_${the_library}_MEXFILES_SRC ${t_SrcFile})
  169. else()
  170. LIST(APPEND nice_${the_library}_SRC ${t_SrcFile})
  171. endif()
  172. endif()
  173. else()
  174. message(STATUS "Not building ${t_SrcFile} because ${t_SrcPath} is excluded (dependencies)")
  175. endif()
  176. endforeach()
  177. ### Get all cpp and tcc files recursively but exclude progs and unit test files
  178. #file(GLOB_RECURSE nice_${the_library}_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp *.tcc)
  179. #filter out source files listed on the blacklist to be excluded from build
  180. if(list_exclude_from_build_SRC)
  181. list( REMOVE_ITEM nice_${the_library}_SRC ${list_exclude_from_build_SRC} )
  182. list( REMOVE_ITEM nice_${the_library}_TESTFILES_SRC ${list_exclude_from_build_SRC} )
  183. endif()
  184. #message(STATUS "globallyrecusive_tests: ${nice_${the_library}_TESTFILES_SRC}")
  185. #message(STATUS "globallyrecusive_progs: ${nice_${the_library}_PROGFILES_SRC}")
  186. ### Get all header files recursively...
  187. # ... but filter the headers according to their "type", meaning whether they are part of a unit test, a prog, or a mex.
  188. # That means for example, that if you DO NOT WANT to build all progs in ./progs/ directories, all header files inside ./progs/ direcories
  189. # should be excluded and not be consided in the build. The same example applies to unit tests (./tests/) and mex filex.
  190. # The reason is: The filter mechanism described above was also appied to source code files. So, we need to take care to have
  191. # the source and header files synchronized, so that we avoid using only the header file of a class, but not its source code implementation file
  192. # which might lead to "undefined references" error. Especially in case of header file class definitions using Qt and an Q_OBJECT
  193. # definition, a header file is moc'ed but but will generate "undefined references" if the source code file is not available.
  194. file(GLOB_RECURSE list_tmp2 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
  195. set(nice_${the_library}_HDR "")
  196. foreach( t_HdrFile ${list_tmp2})
  197. get_filename_component(t_HdrPath ${t_HdrFile} PATH)
  198. set(t_HdrPath ${the_library}/${t_HdrPath})
  199. string(REGEX REPLACE "(.*)/+$" "\\1" t_HdrPath ${t_HdrPath})
  200. #list(FIND internal_deps ${t_HdrPath} dep_index)
  201. if( NOT t_HdrFile MATCHES "moc_" )
  202. if( t_HdrFile MATCHES "tests/" )
  203. if(BUILD_UNITTESTS)
  204. LIST(APPEND nice_${the_library}_HDR ${t_HdrFile})
  205. endif()
  206. elseif( t_HdrFile MATCHES "progs/" )
  207. if(BUILD_PROGRAMS)
  208. #message(STATUS "prog: ${t_HdrFile}")
  209. LIST(APPEND nice_${the_library}_HDR ${t_HdrFile})
  210. endif()
  211. elseif( t_HdrFile MATCHES "Mex[.]" )
  212. if(WITH_MEX)
  213. #message(STATUS "mex: ${t_HdrFile}")
  214. LIST(APPEND nice_${the_library}_HDR ${t_HdrFile})
  215. endif()
  216. else()
  217. LIST(APPEND nice_${the_library}_HDR ${t_HdrFile})
  218. endif()
  219. endif()
  220. endforeach()
  221. #message(STATUS "header files found: ${nice_${the_library}_HDR}")
  222. else()
  223. message(STATUS "Using source files from file lists (*.cmake)")
  224. #define variable nice_<libname>_HDR and nice_<libname>_SRC for library header and source files (don't include progs and test source files here)
  225. include( corefiles.cmake)
  226. #define variable nice_<libname>_PROGFILES_HDR and nice_<libname>_PROGFILES_SRC for program header and source files (don't include library and test source files here)
  227. include( progfiles.cmake)
  228. #define variable nice_<libname>_TESTFILES_HDR and nice_<libname>_TESTFILES_SRC for unit test header and source files (don't include library and progs source files here)
  229. include( testfiles.cmake)
  230. endif()
  231. endmacro()
  232. macro(nice_build_library)
  233. ADD_LIBRARY("nice_${the_library}" ${nice_${the_library}_HDR} ${nice_${the_library}_SRC})
  234. LIST(LENGTH nice_${the_library}_LINKING_DEPENDENCIES dependency_count)
  235. SET(tmp_dependencies "")
  236. IF(dependency_count GREATER 0)
  237. FOREACH(tmp_dependency ${nice_${the_library}_LINKING_DEPENDENCIES})
  238. IF("${tmp_dependency}" MATCHES "^nice_")
  239. STRING(REGEX REPLACE "^nice_(.*)" "\\1" tmp_dependency_nice ${tmp_dependency})
  240. LIST(FIND internal_deps ${tmp_dependency_nice} dep_found)
  241. IF(NOT ${dep_found} LESS 0)
  242. SET(tmp_dependencies ${tmp_dependencies} ${tmp_dependency})
  243. ELSE()
  244. MESSAGE(STATUS "${the_library} wants to link to NICE module: ${tmp_dependency_nice}, but it is not available.")
  245. ENDIF()
  246. ELSE()
  247. SET(tmp_dependencies ${tmp_dependencies} ${tmp_dependency})
  248. ENDIF()
  249. ENDFOREACH()
  250. ENDIF()
  251. SET(nice_${the_library}_LINKING_DEPENDENCIES ${tmp_dependencies})
  252. TARGET_LINK_LIBRARIES("nice_${the_library}" ${nice_${the_library}_LINKING_DEPENDENCIES})
  253. #TARGET_LINK_LIBRARIES("nice_${the_library}" ${nice_${the_library}_LINKING_DEPENDENCIES} ${Boost_LIBRARIES} ${OPENGL_LIBRARY} ${GLUT_LIBRARY} ${QT_LIBRARIES})
  254. SET_PROPERTY(TARGET "nice_${the_library}" PROPERTY FOLDER "library")
  255. INSTALL(TARGETS "nice_${the_library}" DESTINATION lib EXPORT "nice_${the_library}-exports")
  256. INSTALL(EXPORT "nice_${the_library}-exports" DESTINATION lib/exports)
  257. install(DIRECTORY ./ DESTINATION "include/${the_library}"
  258. FILES_MATCHING
  259. PATTERN "*.h"
  260. PATTERN "*.tcc"
  261. PATTERN ".git" EXCLUDE)
  262. configure_file( ../cmake/niceConfig.cmake.in "${PROJECT_BINARY_DIR}/lib/nice_${the_library}Config.cmake" )
  263. endmacro()
  264. # Create builds for all programs that are in the subvariable ${nice_${the_library}_PROGFILES_SRC}
  265. # and build them into "bin/${the_library}"
  266. #
  267. # Variable BUILD_PROGRAMS has to be set and true to invoke progam build. The Variable is controllable
  268. # via the main CMakeLists.txt file (or ccmake)
  269. #
  270. #Note: Variable ${the_library} contains the current (sub-)library name that called this function,
  271. # e.g. ${the_library} == 'core', ${the_library}=='vislearning'
  272. # using subvariables ${nice_${the_library}_PROGFILES_SRC}
  273. #
  274. # Author: Johannes Ruehle
  275. # Date: 2014-02-17
  276. #
  277. macro(nice_add_progs)
  278. if(BUILD_PROGRAMS)
  279. message(STATUS "building progs:")
  280. foreach(__progcpp ${nice_${the_library}_PROGFILES_SRC})
  281. get_filename_component(__progname ${__progcpp} NAME_WE )
  282. #message(STATUS "progname: ${__progname} ${__progcpp}")
  283. set(prog_target_name "${the_library}_${__progname}")
  284. ADD_EXECUTABLE( ${prog_target_name} ${__progcpp})
  285. TARGET_LINK_LIBRARIES(${prog_target_name} "nice_${the_library}")
  286. SET_TARGET_PROPERTIES(${prog_target_name} PROPERTIES OUTPUT_NAME "${__progname}")
  287. INSTALL(TARGETS ${prog_target_name} DESTINATION "bin/${the_library}")
  288. SET_PROPERTY(TARGET ${prog_target_name} PROPERTY FOLDER "programs/${the_library}")
  289. endforeach()
  290. endif()
  291. endmacro()
  292. # Add mex output
  293. macro(nice_add_mexes)
  294. if(WITH_MEX)
  295. message(STATUS "building mexes:")
  296. foreach(__mexcpp ${nice_${the_library}_MEXFILES_SRC})
  297. get_filename_component(__mexname ${__mexcpp} NAME_WE )
  298. message(STATUS "mexname: ${__mexname} ${__mexcpp}")
  299. set(mex_target_name "${the_library}_${__mexname}")
  300. ADD_LIBRARY("${mex_target_name}" SHARED ${__mexcpp})
  301. TARGET_LINK_LIBRARIES(${mex_target_name} "nice_${the_library}")
  302. SET_TARGET_PROPERTIES(${mex_target_name} PROPERTIES OUTPUT_NAME "${__mexname}")
  303. SET_TARGET_PROPERTIES(${mex_target_name} PROPERTIES SUFFIX "${MEX_ENDING}")
  304. SET_TARGET_PROPERTIES(${mex_target_name} PROPERTIES PREFIX "")
  305. INSTALL(TARGETS ${mex_target_name} DESTINATION "bin/${the_library}")
  306. SET_PROPERTY(TARGET ${mex_target_name} PROPERTY FOLDER "programs/${the_library}")
  307. endforeach()
  308. endif()
  309. endmacro()
  310. # Create unit test (using library CppUnitTest) for all cpp files in the subvariable ${nice_${the_library}_TESTFILES_SRC}
  311. # and build them into "bin/${the_library}"
  312. #
  313. # Variable BUILD_UNITTESTS has to be set and true to invoke unit test building.
  314. # The Variable is controllable via the main CMakeLists.txt file (or ccmake)
  315. #
  316. #Note: Variable ${the_library} contains the current (sub-)library name that called this function,
  317. # e.g. ${the_library} == 'core', ${the_library}=='vislearning'
  318. #
  319. # Author: Johannes Ruehle
  320. # Date: 2014-02-17
  321. #
  322. macro(nice_add_unittests)
  323. if(BUILD_UNITTESTS)
  324. INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIR})
  325. message(STATUS "building tests:")
  326. foreach(__testcpp ${nice_${the_library}_TESTFILES_SRC})
  327. get_filename_component(__testname ${__testcpp} NAME_WE )
  328. nice_get_real_path(__testname_abspath ${__testcpp})
  329. get_filename_component(__testname_dir ${__testname_abspath} PATH)
  330. message(STATUS "unittest: ${__testname} ${__testcpp}")
  331. ADD_EXECUTABLE( ${__testname} ../templates/cppUnitTestRunner.cpp ${__testcpp})
  332. TARGET_LINK_LIBRARIES(${__testname} "nice_${the_library}" ${CPPUNIT_LIBRARIES} )
  333. INSTALL(TARGETS ${__testname} DESTINATION "tests/${the_library}")
  334. SET_PROPERTY(TARGET ${__testname} PROPERTY FOLDER "unittests/${the_library}")
  335. ADD_TEST(NAME ${__testname} WORKING_DIRECTORY ${__testname_dir} COMMAND ${__testname})
  336. endforeach()
  337. endif()
  338. endmacro()
  339. # Provides an option that the user can optionally select.
  340. # Can accept condition to control when option is available for user.
  341. # Usage:
  342. # option(<option_variable> "help string describing the option" <initial value or boolean expression> [IF <condition>])
  343. #
  344. # CopyRight: OpenCV
  345. macro(NICE_OPTION variable description value)
  346. set(__value ${value})
  347. set(__condition "")
  348. set(__varname "__value")
  349. foreach(arg ${ARGN})
  350. if(arg STREQUAL "IF" OR arg STREQUAL "if")
  351. set(__varname "__condition")
  352. else()
  353. list(APPEND ${__varname} ${arg})
  354. endif()
  355. endforeach()
  356. unset(__varname)
  357. if("${__condition}" STREQUAL "")
  358. set(__condition 2 GREATER 1)
  359. endif()
  360. if(${__condition})
  361. if("${__value}" MATCHES ";")
  362. if(${__value})
  363. option(${variable} "${description}" ON)
  364. else()
  365. option(${variable} "${description}" OFF)
  366. endif()
  367. elseif(DEFINED ${__value})
  368. if(${__value})
  369. option(${variable} "${description}" ON)
  370. else()
  371. option(${variable} "${description}" OFF)
  372. endif()
  373. else()
  374. option(${variable} "${description}" ${__value})
  375. endif()
  376. else()
  377. unset(${variable} CACHE)
  378. endif()
  379. unset(__condition)
  380. unset(__value)
  381. endmacro()