NiceModules.cmake 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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)
  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. file(GLOB_RECURSE nice_${the_library}_HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
  188. else()
  189. message(STATUS "Using source files from file lists (*.cmake)")
  190. #define variable nice_<libname>_HDR and nice_<libname>_SRC for library header and source files (don't include progs and test source files here)
  191. include( corefiles.cmake)
  192. #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)
  193. include( progfiles.cmake)
  194. #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)
  195. include( testfiles.cmake)
  196. endif()
  197. endmacro()
  198. macro(nice_build_library)
  199. ADD_LIBRARY("nice_${the_library}" ${nice_${the_library}_HDR} ${nice_${the_library}_SRC})
  200. LIST(LENGTH nice_${the_library}_LINKING_DEPENDENCIES dependency_count)
  201. SET(tmp_dependencies "")
  202. IF(dependency_count GREATER 0)
  203. FOREACH(tmp_dependency ${nice_${the_library}_LINKING_DEPENDENCIES})
  204. IF("${tmp_dependency}" MATCHES "^nice_")
  205. STRING(REGEX REPLACE "^nice_(.*)" "\\1" tmp_dependency_nice ${tmp_dependency})
  206. LIST(FIND internal_deps ${tmp_dependency_nice} dep_found)
  207. IF(NOT ${dep_found} LESS 0)
  208. SET(tmp_dependencies ${tmp_dependencies} ${tmp_dependency})
  209. ELSE()
  210. MESSAGE(STATUS "${the_library} wants to link to NICE module: ${tmp_dependency_nice}, but it is not available.")
  211. ENDIF()
  212. ELSE()
  213. SET(tmp_dependencies ${tmp_dependencies} ${tmp_dependency})
  214. ENDIF()
  215. ENDFOREACH()
  216. ENDIF()
  217. SET(nice_${the_library}_LINKING_DEPENDENCIES ${tmp_dependencies})
  218. TARGET_LINK_LIBRARIES("nice_${the_library}" ${nice_${the_library}_LINKING_DEPENDENCIES})
  219. #TARGET_LINK_LIBRARIES("nice_${the_library}" ${nice_${the_library}_LINKING_DEPENDENCIES} ${Boost_LIBRARIES} ${OPENGL_LIBRARY} ${GLUT_LIBRARY} ${QT_LIBRARIES})
  220. SET_PROPERTY(TARGET "nice_${the_library}" PROPERTY FOLDER "library")
  221. INSTALL(TARGETS "nice_${the_library}" DESTINATION lib EXPORT "nice_${the_library}-exports")
  222. INSTALL(EXPORT "nice_${the_library}-exports" DESTINATION lib/exports)
  223. install(DIRECTORY ./ DESTINATION "include/${the_library}"
  224. FILES_MATCHING
  225. PATTERN "*.h"
  226. PATTERN "*.tcc"
  227. PATTERN ".git" EXCLUDE)
  228. configure_file( ../cmake/niceConfig.cmake.in "${PROJECT_BINARY_DIR}/lib/nice_${the_library}Config.cmake" )
  229. endmacro()
  230. # Create builds for all programs that are in the subvariable ${nice_${the_library}_PROGFILES_SRC}
  231. # and build them into "bin/${the_library}"
  232. #
  233. # Variable BUILD_PROGRAMS has to be set and true to invoke progam build. The Variable is controllable
  234. # via the main CMakeLists.txt file (or ccmake)
  235. #
  236. #Note: Variable ${the_library} contains the current (sub-)library name that called this function,
  237. # e.g. ${the_library} == 'core', ${the_library}=='vislearning'
  238. # using subvariables ${nice_${the_library}_PROGFILES_SRC}
  239. #
  240. # Author: Johannes Ruehle
  241. # Date: 2014-02-17
  242. #
  243. macro(nice_add_progs)
  244. if(BUILD_PROGRAMS)
  245. message(STATUS "building progs:")
  246. foreach(__progcpp ${nice_${the_library}_PROGFILES_SRC})
  247. get_filename_component(__progname ${__progcpp} NAME_WE )
  248. #message(STATUS "progname: ${__progname} ${__progcpp}")
  249. set(prog_target_name "${the_library}_${__progname}")
  250. ADD_EXECUTABLE( ${prog_target_name} ${__progcpp})
  251. TARGET_LINK_LIBRARIES(${prog_target_name} "nice_${the_library}")
  252. SET_TARGET_PROPERTIES(${prog_target_name} PROPERTIES OUTPUT_NAME "${__progname}")
  253. INSTALL(TARGETS ${prog_target_name} DESTINATION "bin/${the_library}")
  254. SET_PROPERTY(TARGET ${prog_target_name} PROPERTY FOLDER "programs/${the_library}")
  255. endforeach()
  256. endif()
  257. endmacro()
  258. # Add mex output
  259. macro(nice_add_mexes)
  260. if(WITH_MEX)
  261. message(STATUS "building mexes:")
  262. foreach(__mexcpp ${nice_${the_library}_MEXFILES_SRC})
  263. get_filename_component(__mexname ${__mexcpp} NAME_WE )
  264. message(STATUS "mexname: ${__mexname} ${__mexcpp}")
  265. set(mex_target_name "${the_library}_${__mexname}")
  266. ADD_LIBRARY("${mex_target_name}" SHARED ${__mexcpp})
  267. TARGET_LINK_LIBRARIES(${mex_target_name} "nice_${the_library}")
  268. SET_TARGET_PROPERTIES(${mex_target_name} PROPERTIES OUTPUT_NAME "${__mexname}")
  269. SET_TARGET_PROPERTIES(${mex_target_name} PROPERTIES SUFFIX "${MEX_ENDING}")
  270. SET_TARGET_PROPERTIES(${mex_target_name} PROPERTIES PREFIX "")
  271. INSTALL(TARGETS ${mex_target_name} DESTINATION "bin/${the_library}")
  272. SET_PROPERTY(TARGET ${mex_target_name} PROPERTY FOLDER "programs/${the_library}")
  273. endforeach()
  274. endif()
  275. endmacro()
  276. # Create unit test (using library CppUnitTest) for all cpp files in the subvariable ${nice_${the_library}_TESTFILES_SRC}
  277. # and build them into "bin/${the_library}"
  278. #
  279. # Variable BUILD_UNITTESTS has to be set and true to invoke unit test building.
  280. # The Variable is controllable via the main CMakeLists.txt file (or ccmake)
  281. #
  282. #Note: Variable ${the_library} contains the current (sub-)library name that called this function,
  283. # e.g. ${the_library} == 'core', ${the_library}=='vislearning'
  284. #
  285. # Author: Johannes Ruehle
  286. # Date: 2014-02-17
  287. #
  288. macro(nice_add_unittests)
  289. if(BUILD_UNITTESTS)
  290. INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIR})
  291. message(STATUS "building tests:")
  292. foreach(__testcpp ${nice_${the_library}_TESTFILES_SRC})
  293. get_filename_component(__testname ${__testcpp} NAME_WE )
  294. nice_get_real_path(__testname_abspath ${__testcpp})
  295. get_filename_component(__testname_dir ${__testname_abspath} PATH)
  296. message(STATUS "unittest: ${__testname} ${__testcpp}")
  297. ADD_EXECUTABLE( ${__testname} ../templates/cppUnitTestRunner.cpp ${__testcpp})
  298. TARGET_LINK_LIBRARIES(${__testname} "nice_${the_library}" ${CPPUNIT_LIBRARIES} )
  299. INSTALL(TARGETS ${__testname} DESTINATION "tests/${the_library}")
  300. SET_PROPERTY(TARGET ${__testname} PROPERTY FOLDER "unittests/${the_library}")
  301. ADD_TEST(NAME ${__testname} WORKING_DIRECTORY ${__testname_dir} COMMAND ${__testname})
  302. endforeach()
  303. endif()
  304. endmacro()
  305. # Provides an option that the user can optionally select.
  306. # Can accept condition to control when option is available for user.
  307. # Usage:
  308. # option(<option_variable> "help string describing the option" <initial value or boolean expression> [IF <condition>])
  309. #
  310. # CopyRight: OpenCV
  311. macro(NICE_OPTION variable description value)
  312. set(__value ${value})
  313. set(__condition "")
  314. set(__varname "__value")
  315. foreach(arg ${ARGN})
  316. if(arg STREQUAL "IF" OR arg STREQUAL "if")
  317. set(__varname "__condition")
  318. else()
  319. list(APPEND ${__varname} ${arg})
  320. endif()
  321. endforeach()
  322. unset(__varname)
  323. if("${__condition}" STREQUAL "")
  324. set(__condition 2 GREATER 1)
  325. endif()
  326. if(${__condition})
  327. if("${__value}" MATCHES ";")
  328. if(${__value})
  329. option(${variable} "${description}" ON)
  330. else()
  331. option(${variable} "${description}" OFF)
  332. endif()
  333. elseif(DEFINED ${__value})
  334. if(${__value})
  335. option(${variable} "${description}" ON)
  336. else()
  337. option(${variable} "${description}" OFF)
  338. endif()
  339. else()
  340. option(${variable} "${description}" ${__value})
  341. endif()
  342. else()
  343. unset(${variable} CACHE)
  344. endif()
  345. unset(__condition)
  346. unset(__value)
  347. endmacro()