cc_rules.cmake 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. # Copyright 2017 Google
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. include(CMakeParseArguments)
  15. # cc_library(
  16. # target
  17. # SOURCES sources...
  18. # DEPENDS libraries...
  19. # [EXCLUDE_FROM_ALL]
  20. # )
  21. #
  22. # Defines a new library target with the given target name, sources, and
  23. # dependencies.
  24. function(cc_library name)
  25. set(flag EXCLUDE_FROM_ALL)
  26. set(multi DEPENDS SOURCES)
  27. cmake_parse_arguments(ccl "${flag}" "" "${multi}" ${ARGN})
  28. maybe_remove_objc_sources(sources ${ccl_SOURCES})
  29. add_library(${name} ${sources})
  30. add_objc_flags(${name} ccl)
  31. target_include_directories(
  32. ${name}
  33. PUBLIC
  34. # Put the binary dir first so that the generated config.h trumps any one
  35. # generated statically by a Cocoapods-based build in the same source tree.
  36. ${FIREBASE_BINARY_DIR}
  37. ${FIREBASE_SOURCE_DIR}
  38. )
  39. target_link_libraries(${name} PUBLIC ${ccl_DEPENDS})
  40. if(ccl_EXCLUDE_FROM_ALL)
  41. set_property(
  42. TARGET ${name}
  43. PROPERTY EXCLUDE_FROM_ALL ON
  44. )
  45. endif()
  46. endfunction()
  47. # cc_select(
  48. # interface_library
  49. # CONDITION1 implementation_library1
  50. # [CONDITION2 implementation_library2 ...]
  51. # [DEFAULT implementation_library_default]
  52. # )
  53. #
  54. # Creates an INTERFACE library named `interface_library`.
  55. #
  56. # For each pair of condition and implementation_library, evaluates the condition
  57. # and if true makes that library an INTERFACE link library of
  58. # `interface_library`.
  59. #
  60. # If supplied, uses the `DEFAULT` implementation if no other condition matches.
  61. #
  62. # If no condition matches, fails the configuration cycle with an error message
  63. # indicating that no suitable implementation was found.
  64. function(cc_select library_name)
  65. add_library(${library_name} INTERFACE)
  66. list(LENGTH ARGN length)
  67. if(length GREATER 0)
  68. math(EXPR length "${length} - 1")
  69. foreach(key RANGE 0 ${length} 2)
  70. math(EXPR value "${key} + 1")
  71. list(GET ARGN ${key} condition)
  72. list(GET ARGN ${value} impl_library)
  73. if((${condition} STREQUAL "DEFAULT") OR (${${condition}}))
  74. message("Using ${library_name} = ${impl_library}")
  75. target_link_libraries(
  76. ${library_name} INTERFACE ${impl_library}
  77. )
  78. return()
  79. endif()
  80. endforeach()
  81. endif()
  82. message(FATAL_ERROR "Could not find implementation for ${library_name}")
  83. endfunction()
  84. # cc_binary(
  85. # target
  86. # SOURCES sources...
  87. # DEPENDS libraries...
  88. # [EXCLUDE_FROM_ALL]
  89. # )
  90. #
  91. # Defines a new executable target with the given target name, sources, and
  92. # dependencies.
  93. function(cc_binary name)
  94. set(flag EXCLUDE_FROM_ALL)
  95. set(multi DEPENDS SOURCES)
  96. cmake_parse_arguments(ccb "${flag}" "" "${multi}" ${ARGN})
  97. maybe_remove_objc_sources(sources ${ccb_SOURCES})
  98. add_executable(${name} ${sources})
  99. add_objc_flags(${name} ccb)
  100. add_test(${name} ${name})
  101. target_include_directories(${name} PUBLIC ${FIREBASE_SOURCE_DIR})
  102. target_link_libraries(${name} ${ccb_DEPENDS})
  103. if(ccb_EXCLUDE_FROM_ALL)
  104. set_property(
  105. TARGET ${name}
  106. PROPERTY EXCLUDE_FROM_ALL ON
  107. )
  108. endif()
  109. endfunction()
  110. # cc_test(
  111. # target
  112. # SOURCES sources...
  113. # DEPENDS libraries...
  114. # )
  115. #
  116. # Defines a new test executable target with the given target name, sources, and
  117. # dependencies. Implicitly adds DEPENDS on GTest::GTest and GTest::Main.
  118. function(cc_test name)
  119. set(multi DEPENDS SOURCES)
  120. cmake_parse_arguments(cct "" "" "${multi}" ${ARGN})
  121. list(APPEND cct_DEPENDS GTest::GTest GTest::Main)
  122. maybe_remove_objc_sources(sources ${cct_SOURCES})
  123. add_executable(${name} ${sources})
  124. add_objc_flags(${name} cct)
  125. add_test(${name} ${name})
  126. target_include_directories(${name} PUBLIC ${FIREBASE_SOURCE_DIR})
  127. target_link_libraries(${name} ${cct_DEPENDS})
  128. endfunction()
  129. # cc_fuzz_test(
  130. # target
  131. # DICTIONARY dict_file
  132. # CORPUS corpus_dir
  133. # SOURCES sources...
  134. # DEPENDS libraries...
  135. # )
  136. #
  137. # Defines a new executable fuzz testing target with the given target name,
  138. # (optional) dictionary file, (optional) corpus directory, sources, and
  139. # dependencies. Implicitly adds DEPENDS on 'Fuzzer', which corresponds to
  140. # libFuzzer if fuzzing runs locally or a provided fuzzing library if fuzzing
  141. # runs on OSS Fuzz. If provided, copies the DICTIONARY file as '${target}.dict'
  142. # and copies the CORPUS directory as '${target}_seed_corpus' after building the
  143. # target. This naming convention is critical for OSS Fuzz build script to
  144. # capture new fuzzing targets.
  145. function(cc_fuzz_test name)
  146. # Finds the fuzzer library that is either provided by OSS Fuzz or libFuzzer
  147. # that is manually built from sources.
  148. find_package(Fuzzer REQUIRED)
  149. # Parse arguments of the cc_fuzz_test macro.
  150. set(single DICTIONARY CORPUS)
  151. set(multi DEPENDS SOURCES)
  152. cmake_parse_arguments(ccf "" "${single}" "${multi}" ${ARGN})
  153. list(APPEND ccf_DEPENDS Fuzzer)
  154. cc_binary(
  155. ${name}
  156. SOURCES ${ccf_SOURCES}
  157. DEPENDS ${ccf_DEPENDS}
  158. )
  159. # Copy the dictionary file and corpus directory, if they are defined.
  160. if(DEFINED ccf_DICTIONARY)
  161. add_custom_command(
  162. TARGET ${name} POST_BUILD
  163. COMMAND ${CMAKE_COMMAND} -E copy
  164. ${ccf_DICTIONARY} ${name}.dict
  165. )
  166. endif()
  167. if(DEFINED ccf_CORPUS)
  168. add_custom_command(
  169. TARGET ${name} POST_BUILD
  170. COMMAND ${CMAKE_COMMAND} -E copy_directory
  171. ${ccf_CORPUS} ${name}_seed_corpus
  172. )
  173. endif()
  174. endfunction()
  175. # maybe_remove_objc_sources(output_var sources...)
  176. #
  177. # Removes Objective-C/C++ sources from the given sources if not on an Apple
  178. # platform. Stores the resulting list in the variable named by `output_var`.
  179. function(maybe_remove_objc_sources output_var)
  180. unset(sources)
  181. foreach(source ${ARGN})
  182. get_filename_component(ext ${source} EXT)
  183. if(NOT APPLE AND ((ext STREQUAL ".m") OR (ext STREQUAL ".mm")))
  184. continue()
  185. endif()
  186. list(APPEND sources ${source})
  187. endforeach()
  188. set(${output_var} ${sources} PARENT_SCOPE)
  189. endfunction()
  190. # add_objc_flags(target sources...)
  191. #
  192. # Adds OBJC_FLAGS to the compile options of the given target if any of the
  193. # sources have filenames that indicate they are are Objective-C.
  194. function(add_objc_flags target)
  195. set(_has_objc OFF)
  196. foreach(source ${ARGN})
  197. get_filename_component(ext ${source} EXT)
  198. if((ext STREQUAL ".m") OR (ext STREQUAL ".mm"))
  199. set(_has_objc ON)
  200. endif()
  201. endforeach()
  202. if(_has_objc)
  203. target_compile_options(
  204. ${target}
  205. PRIVATE
  206. ${OBJC_FLAGS}
  207. )
  208. endif()
  209. endfunction()
  210. # add_alias(alias_target actual_target)
  211. #
  212. # Adds a library alias target `alias_target` if it does not already exist,
  213. # aliasing to the given `actual_target` target. This allows library dependencies
  214. # to be specified uniformly in terms of the targets found in various
  215. # find_package modules even if the library is being built internally.
  216. function(add_alias ALIAS_TARGET ACTUAL_TARGET)
  217. if(NOT TARGET ${ALIAS_TARGET})
  218. add_library(${ALIAS_TARGET} ALIAS ${ACTUAL_TARGET})
  219. endif()
  220. endfunction()