NiceModules.cmake 15 KB

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