draco_targets.cmake 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. if(DRACO_CMAKE_DRACO_TARGETS_CMAKE_)
  2. return()
  3. endif() # DRACO_CMAKE_DRACO_TARGETS_CMAKE_
  4. set(DRACO_CMAKE_DRACO_TARGETS_CMAKE_ 1)
  5. # Resets list variables used to track draco targets.
  6. macro(draco_reset_target_lists)
  7. unset(draco_targets)
  8. unset(draco_exe_targets)
  9. unset(draco_lib_targets)
  10. unset(draco_objlib_targets)
  11. unset(draco_module_targets)
  12. unset(draco_sources)
  13. unset(draco_test_targets)
  14. endmacro()
  15. # Creates an executable target. The target name is passed as a parameter to the
  16. # NAME argument, and the sources passed as a parameter to the SOURCES argument:
  17. # draco_add_executable(NAME <name> SOURCES <sources> [optional args])
  18. #
  19. # Optional args:
  20. # cmake-format: off
  21. # - OUTPUT_NAME: Override output file basename. Target basename defaults to
  22. # NAME.
  23. # - TEST: Flag. Presence means treat executable as a test.
  24. # - DEFINES: List of preprocessor macro definitions.
  25. # - INCLUDES: list of include directories for the target.
  26. # - COMPILE_FLAGS: list of compiler flags for the target.
  27. # - LINK_FLAGS: List of linker flags for the target.
  28. # - OBJLIB_DEPS: List of CMake object library target dependencies.
  29. # - LIB_DEPS: List of CMake library dependencies.
  30. # cmake-format: on
  31. #
  32. # Sources passed to this macro are added to $draco_test_sources when TEST is
  33. # specified. Otherwise sources are added to $draco_sources.
  34. #
  35. # Targets passed to this macro are always added to the $draco_targets list. When
  36. # TEST is specified targets are also added to the $draco_test_targets list.
  37. # Otherwise targets are added to $draco_exe_targets.
  38. macro(draco_add_executable)
  39. unset(exe_TEST)
  40. unset(exe_TEST_DEFINES_MAIN)
  41. unset(exe_NAME)
  42. unset(exe_OUTPUT_NAME)
  43. unset(exe_SOURCES)
  44. unset(exe_DEFINES)
  45. unset(exe_INCLUDES)
  46. unset(exe_COMPILE_FLAGS)
  47. unset(exe_LINK_FLAGS)
  48. unset(exe_OBJLIB_DEPS)
  49. unset(exe_LIB_DEPS)
  50. set(optional_args TEST)
  51. set(single_value_args NAME OUTPUT_NAME)
  52. set(multi_value_args SOURCES DEFINES INCLUDES COMPILE_FLAGS LINK_FLAGS
  53. OBJLIB_DEPS LIB_DEPS)
  54. cmake_parse_arguments(exe "${optional_args}" "${single_value_args}"
  55. "${multi_value_args}" ${ARGN})
  56. if(DRACO_VERBOSE GREATER 1)
  57. message("--------- draco_add_executable ---------\n"
  58. "exe_TEST=${exe_TEST}\n"
  59. "exe_TEST_DEFINES_MAIN=${exe_TEST_DEFINES_MAIN}\n"
  60. "exe_NAME=${exe_NAME}\n"
  61. "exe_OUTPUT_NAME=${exe_OUTPUT_NAME}\n"
  62. "exe_SOURCES=${exe_SOURCES}\n"
  63. "exe_DEFINES=${exe_DEFINES}\n"
  64. "exe_INCLUDES=${exe_INCLUDES}\n"
  65. "exe_COMPILE_FLAGS=${exe_COMPILE_FLAGS}\n"
  66. "exe_LINK_FLAGS=${exe_LINK_FLAGS}\n"
  67. "exe_OBJLIB_DEPS=${exe_OBJLIB_DEPS}\n"
  68. "exe_LIB_DEPS=${exe_LIB_DEPS}\n"
  69. "------------------------------------------\n")
  70. endif()
  71. if(NOT (exe_NAME AND exe_SOURCES))
  72. message(FATAL_ERROR "draco_add_executable: NAME and SOURCES required.")
  73. endif()
  74. list(APPEND draco_targets ${exe_NAME})
  75. if(exe_TEST)
  76. list(APPEND draco_test_targets ${exe_NAME})
  77. list(APPEND draco_test_sources ${exe_SOURCES})
  78. else()
  79. list(APPEND draco_exe_targets ${exe_NAME})
  80. list(APPEND draco_sources ${exe_SOURCES})
  81. endif()
  82. add_executable(${exe_NAME} ${exe_SOURCES})
  83. set_target_properties(${exe_NAME} PROPERTIES VERSION ${DRACO_VERSION})
  84. if(exe_OUTPUT_NAME)
  85. set_target_properties(${exe_NAME} PROPERTIES OUTPUT_NAME ${exe_OUTPUT_NAME})
  86. endif()
  87. draco_process_intrinsics_sources(TARGET ${exe_NAME} SOURCES ${exe_SOURCES})
  88. if(exe_DEFINES)
  89. target_compile_definitions(${exe_NAME} PRIVATE ${exe_DEFINES})
  90. endif()
  91. if(exe_INCLUDES)
  92. target_include_directories(${exe_NAME} PRIVATE ${exe_INCLUDES})
  93. endif()
  94. if(exe_COMPILE_FLAGS OR DRACO_CXX_FLAGS)
  95. target_compile_options(${exe_NAME}
  96. PRIVATE ${exe_COMPILE_FLAGS} ${DRACO_CXX_FLAGS})
  97. endif()
  98. if(exe_LINK_FLAGS OR DRACO_EXE_LINKER_FLAGS)
  99. if(${CMAKE_VERSION} VERSION_LESS "3.13")
  100. list(APPEND exe_LINK_FLAGS "${DRACO_EXE_LINKER_FLAGS}")
  101. # LINK_FLAGS is managed as a string.
  102. draco_set_and_stringify(SOURCE "${exe_LINK_FLAGS}" DEST exe_LINK_FLAGS)
  103. set_target_properties(${exe_NAME}
  104. PROPERTIES LINK_FLAGS "${exe_LINK_FLAGS}")
  105. else()
  106. target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS}
  107. ${DRACO_EXE_LINKER_FLAGS})
  108. endif()
  109. endif()
  110. if(exe_OBJLIB_DEPS)
  111. foreach(objlib_dep ${exe_OBJLIB_DEPS})
  112. target_sources(${exe_NAME} PRIVATE $<TARGET_OBJECTS:${objlib_dep}>)
  113. endforeach()
  114. endif()
  115. if(CMAKE_THREAD_LIBS_INIT)
  116. list(APPEND exe_LIB_DEPS ${CMAKE_THREAD_LIBS_INIT})
  117. endif()
  118. if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))
  119. target_compile_definitions(${exe_NAME} PRIVATE "DRACO_BUILDING_DLL=0")
  120. endif()
  121. if(exe_LIB_DEPS)
  122. unset(exe_static)
  123. if("${CMAKE_EXE_LINKER_FLAGS} ${DRACO_EXE_LINKER_FLAGS}" MATCHES "static")
  124. set(exe_static ON)
  125. endif()
  126. if(exe_static AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
  127. # Third party dependencies can introduce dependencies on system and test
  128. # libraries. Since the target created here is an executable, and CMake
  129. # does not provide a method of controlling order of link dependencies,
  130. # wrap all of the dependencies of this target in start/end group flags to
  131. # ensure that dependencies of third party targets can be resolved when
  132. # those dependencies happen to be resolved by dependencies of the current
  133. # target.
  134. list(INSERT exe_LIB_DEPS 0 -Wl,--start-group)
  135. list(APPEND exe_LIB_DEPS -Wl,--end-group)
  136. endif()
  137. target_link_libraries(${exe_NAME} PRIVATE ${exe_LIB_DEPS})
  138. endif()
  139. endmacro()
  140. # Creates a library target of the specified type. The target name is passed as a
  141. # parameter to the NAME argument, the type as a parameter to the TYPE argument,
  142. # and the sources passed as a parameter to the SOURCES argument:
  143. # draco_add_library(NAME <name> TYPE <type> SOURCES <sources> [optional args])
  144. #
  145. # Optional args:
  146. # cmake-format: off
  147. # - OUTPUT_NAME: Override output file basename. Target basename defaults to
  148. # NAME. OUTPUT_NAME is ignored when BUILD_SHARED_LIBS is enabled and CMake
  149. # is generating a build for which MSVC is true. This is to avoid output
  150. # basename collisions with DLL import libraries.
  151. # - TEST: Flag. Presence means treat library as a test.
  152. # - DEFINES: List of preprocessor macro definitions.
  153. # - INCLUDES: list of include directories for the target.
  154. # - COMPILE_FLAGS: list of compiler flags for the target.
  155. # - LINK_FLAGS: List of linker flags for the target.
  156. # - OBJLIB_DEPS: List of CMake object library target dependencies.
  157. # - LIB_DEPS: List of CMake library dependencies.
  158. # - PUBLIC_INCLUDES: List of include paths to export to dependents.
  159. # cmake-format: on
  160. #
  161. # Sources passed to the macro are added to the lists tracking draco sources:
  162. # cmake-format: off
  163. # - When TEST is specified sources are added to $draco_test_sources.
  164. # - Otherwise sources are added to $draco_sources.
  165. # cmake-format: on
  166. #
  167. # Targets passed to this macro are added to the lists tracking draco targets:
  168. # cmake-format: off
  169. # - Targets are always added to $draco_targets.
  170. # - When the TEST flag is specified, targets are added to
  171. # $draco_test_targets.
  172. # - When TEST is not specified:
  173. # - Libraries of type SHARED are added to $draco_dylib_targets.
  174. # - Libraries of type OBJECT are added to $draco_objlib_targets.
  175. # - Libraries of type STATIC are added to $draco_lib_targets.
  176. # cmake-format: on
  177. macro(draco_add_library)
  178. unset(lib_TEST)
  179. unset(lib_NAME)
  180. unset(lib_OUTPUT_NAME)
  181. unset(lib_TYPE)
  182. unset(lib_SOURCES)
  183. unset(lib_DEFINES)
  184. unset(lib_INCLUDES)
  185. unset(lib_COMPILE_FLAGS)
  186. unset(lib_LINK_FLAGS)
  187. unset(lib_OBJLIB_DEPS)
  188. unset(lib_LIB_DEPS)
  189. unset(lib_PUBLIC_INCLUDES)
  190. unset(lib_TARGET_PROPERTIES)
  191. set(optional_args TEST)
  192. set(single_value_args NAME OUTPUT_NAME TYPE)
  193. set(multi_value_args SOURCES DEFINES INCLUDES COMPILE_FLAGS LINK_FLAGS
  194. OBJLIB_DEPS LIB_DEPS PUBLIC_INCLUDES TARGET_PROPERTIES)
  195. cmake_parse_arguments(lib "${optional_args}" "${single_value_args}"
  196. "${multi_value_args}" ${ARGN})
  197. if(DRACO_VERBOSE GREATER 1)
  198. message("--------- draco_add_library ---------\n"
  199. "lib_TEST=${lib_TEST}\n"
  200. "lib_NAME=${lib_NAME}\n"
  201. "lib_OUTPUT_NAME=${lib_OUTPUT_NAME}\n"
  202. "lib_TYPE=${lib_TYPE}\n"
  203. "lib_SOURCES=${lib_SOURCES}\n"
  204. "lib_DEFINES=${lib_DEFINES}\n"
  205. "lib_INCLUDES=${lib_INCLUDES}\n"
  206. "lib_COMPILE_FLAGS=${lib_COMPILE_FLAGS}\n"
  207. "lib_LINK_FLAGS=${lib_LINK_FLAGS}\n"
  208. "lib_OBJLIB_DEPS=${lib_OBJLIB_DEPS}\n"
  209. "lib_LIB_DEPS=${lib_LIB_DEPS}\n"
  210. "lib_PUBLIC_INCLUDES=${lib_PUBLIC_INCLUDES}\n"
  211. "---------------------------------------\n")
  212. endif()
  213. if(NOT (lib_NAME AND lib_TYPE))
  214. message(FATAL_ERROR "draco_add_library: NAME and TYPE required.")
  215. endif()
  216. list(APPEND draco_targets ${lib_NAME})
  217. if(lib_TEST)
  218. list(APPEND draco_test_targets ${lib_NAME})
  219. list(APPEND draco_test_sources ${lib_SOURCES})
  220. else()
  221. list(APPEND draco_sources ${lib_SOURCES})
  222. if(lib_TYPE STREQUAL MODULE)
  223. list(APPEND draco_module_targets ${lib_NAME})
  224. elseif(lib_TYPE STREQUAL OBJECT)
  225. list(APPEND draco_objlib_targets ${lib_NAME})
  226. elseif(lib_TYPE STREQUAL SHARED)
  227. list(APPEND draco_dylib_targets ${lib_NAME})
  228. elseif(lib_TYPE STREQUAL STATIC)
  229. list(APPEND draco_lib_targets ${lib_NAME})
  230. else()
  231. message(WARNING "draco_add_library: Unhandled type: ${lib_TYPE}")
  232. endif()
  233. endif()
  234. add_library(${lib_NAME} ${lib_TYPE} ${lib_SOURCES})
  235. if(lib_SOURCES)
  236. draco_process_intrinsics_sources(TARGET ${lib_NAME} SOURCES ${lib_SOURCES})
  237. endif()
  238. if(lib_OUTPUT_NAME)
  239. if(NOT (BUILD_SHARED_LIBS AND MSVC))
  240. set_target_properties(${lib_NAME}
  241. PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME})
  242. endif()
  243. endif()
  244. if(lib_DEFINES)
  245. target_compile_definitions(${lib_NAME} PRIVATE ${lib_DEFINES})
  246. endif()
  247. if(lib_INCLUDES)
  248. target_include_directories(${lib_NAME} PRIVATE ${lib_INCLUDES})
  249. endif()
  250. if(lib_PUBLIC_INCLUDES)
  251. target_include_directories(${lib_NAME} PUBLIC ${lib_PUBLIC_INCLUDES})
  252. endif()
  253. if(lib_COMPILE_FLAGS OR DRACO_CXX_FLAGS)
  254. target_compile_options(${lib_NAME}
  255. PRIVATE ${lib_COMPILE_FLAGS} ${DRACO_CXX_FLAGS})
  256. endif()
  257. if(lib_LINK_FLAGS)
  258. set_target_properties(${lib_NAME} PROPERTIES LINK_FLAGS ${lib_LINK_FLAGS})
  259. endif()
  260. if(lib_OBJLIB_DEPS)
  261. foreach(objlib_dep ${lib_OBJLIB_DEPS})
  262. target_sources(${lib_NAME} PRIVATE $<TARGET_OBJECTS:${objlib_dep}>)
  263. endforeach()
  264. endif()
  265. if(lib_LIB_DEPS)
  266. if(lib_TYPE STREQUAL STATIC)
  267. set(link_type PUBLIC)
  268. else()
  269. set(link_type PRIVATE)
  270. if(lib_TYPE STREQUAL SHARED AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
  271. # The draco shared object uses the static draco as input to turn it into
  272. # a shared object. Include everything from the static library in the
  273. # shared object.
  274. if(APPLE)
  275. list(INSERT lib_LIB_DEPS 0 -Wl,-force_load)
  276. else()
  277. list(INSERT lib_LIB_DEPS 0 -Wl,--whole-archive)
  278. list(APPEND lib_LIB_DEPS -Wl,--no-whole-archive)
  279. endif()
  280. endif()
  281. endif()
  282. target_link_libraries(${lib_NAME} ${link_type} ${lib_LIB_DEPS})
  283. endif()
  284. if(NOT MSVC AND lib_NAME MATCHES "^lib")
  285. # Non-MSVC generators prepend lib to static lib target file names. Libdraco
  286. # already includes lib in its name. Avoid naming output files liblib*.
  287. set_target_properties(${lib_NAME} PROPERTIES PREFIX "")
  288. endif()
  289. # VERSION and SOVERSION as necessary
  290. if(NOT lib_TYPE STREQUAL STATIC AND NOT lib_TYPE STREQUAL MODULE)
  291. set_target_properties(${lib_NAME} PROPERTIES VERSION ${DRACO_VERSION})
  292. if(NOT MSVC)
  293. set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION})
  294. endif()
  295. endif()
  296. if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))
  297. if(lib_TYPE STREQUAL SHARED)
  298. target_compile_definitions(${lib_NAME} PRIVATE "DRACO_BUILDING_DLL=1")
  299. else()
  300. target_compile_definitions(${lib_NAME} PRIVATE "DRACO_BUILDING_DLL=0")
  301. endif()
  302. endif()
  303. # Determine if $lib_NAME is a header only target.
  304. unset(sources_list)
  305. if(lib_SOURCES)
  306. set(sources_list ${lib_SOURCES})
  307. list(FILTER sources_list INCLUDE REGEX cc$)
  308. endif()
  309. if(NOT sources_list)
  310. if(NOT XCODE)
  311. # This is a header only target. Tell CMake the link language.
  312. set_target_properties(${lib_NAME} PROPERTIES LINKER_LANGUAGE CXX)
  313. else()
  314. # The Xcode generator ignores LINKER_LANGUAGE. Add a dummy cc file.
  315. draco_create_dummy_source_file(TARGET ${lib_NAME} BASENAME ${lib_NAME})
  316. endif()
  317. endif()
  318. endmacro()