ECMFindModuleHelpers.cmake 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #.rst:
  2. # ECMFindModuleHelpers
  3. # --------------------
  4. #
  5. # Helper macros for find modules: ecm_find_package_version_check(),
  6. # ecm_find_package_parse_components() and
  7. # ecm_find_package_handle_library_components().
  8. #
  9. # ::
  10. #
  11. # ecm_find_package_version_check(<name>)
  12. #
  13. # Prints warnings if the CMake version or the project's required CMake version
  14. # is older than that required by extra-cmake-modules.
  15. #
  16. # ::
  17. #
  18. # ecm_find_package_parse_components(<name>
  19. # RESULT_VAR <variable>
  20. # KNOWN_COMPONENTS <component1> [<component2> [...]]
  21. # [SKIP_DEPENDENCY_HANDLING])
  22. #
  23. # This macro will populate <variable> with a list of components found in
  24. # <name>_FIND_COMPONENTS, after checking that all those components are in the
  25. # list of KNOWN_COMPONENTS; if there are any unknown components, it will print
  26. # an error or warning (depending on the value of <name>_FIND_REQUIRED) and call
  27. # return().
  28. #
  29. # The order of components in <variable> is guaranteed to match the order they
  30. # are listed in the KNOWN_COMPONENTS argument.
  31. #
  32. # If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable
  33. # <name>_<component>_component_deps will be checked for dependent components.
  34. # If <component> is listed in <name>_FIND_COMPONENTS, then all its (transitive)
  35. # dependencies will also be added to <variable>.
  36. #
  37. # ::
  38. #
  39. # ecm_find_package_handle_library_components(<name>
  40. # COMPONENTS <component> [<component> [...]]
  41. # [SKIP_DEPENDENCY_HANDLING])
  42. # [SKIP_PKG_CONFIG])
  43. #
  44. # Creates an imported library target for each component. The operation of this
  45. # macro depends on the presence of a number of CMake variables.
  46. #
  47. # The <name>_<component>_lib variable should contain the name of this library,
  48. # and <name>_<component>_header variable should contain the name of a header
  49. # file associated with it (whatever relative path is normally passed to
  50. # '#include'). <name>_<component>_header_subdir variable can be used to specify
  51. # which subdirectory of the include path the headers will be found in.
  52. # ecm_find_package_components() will then search for the library
  53. # and include directory (creating appropriate cache variables) and create an
  54. # imported library target named <name>::<component>.
  55. #
  56. # Additional variables can be used to provide additional information:
  57. #
  58. # If SKIP_PKG_CONFIG, the <name>_<component>_pkg_config variable is set, and
  59. # pkg-config is found, the pkg-config module given by
  60. # <name>_<component>_pkg_config will be searched for and used to help locate the
  61. # library and header file. It will also be used to set
  62. # <name>_<component>_VERSION.
  63. #
  64. # Note that if version information is found via pkg-config,
  65. # <name>_<component>_FIND_VERSION can be set to require a particular version
  66. # for each component.
  67. #
  68. # If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property
  69. # of the imported target for <component> will be set to contain the imported
  70. # targets for the components listed in <name>_<component>_component_deps.
  71. # <component>_FOUND will also be set to false if any of the compoments in
  72. # <name>_<component>_component_deps are not found. This requires the components
  73. # in <name>_<component>_component_deps to be listed before <component> in the
  74. # COMPONENTS argument.
  75. #
  76. # The following variables will be set:
  77. #
  78. # ``<name>_TARGETS``
  79. # the imported targets
  80. # ``<name>_LIBRARIES``
  81. # the found libraries
  82. # ``<name>_INCLUDE_DIRS``
  83. # the combined required include directories for the components
  84. # ``<name>_DEFINITIONS``
  85. # the "other" CFLAGS provided by pkg-config, if any
  86. # ``<name>_VERSION``
  87. # the value of ``<name>_<component>_VERSION`` for the first component that
  88. # has this variable set (note that components are searched for in the order
  89. # they are passed to the macro), although if it is already set, it will not
  90. # be altered
  91. #
  92. # Note that these variables are never cleared, so if
  93. # ecm_find_package_handle_library_components() is called multiple times with
  94. # different components (typically because of multiple find_package() calls) then
  95. # ``<name>_TARGETS``, for example, will contain all the targets found in any
  96. # call (although no duplicates).
  97. #
  98. # Since pre-1.0.0.
  99. #=============================================================================
  100. # Copyright 2014 Alex Merry <alex.merry@kde.org>
  101. #
  102. # Redistribution and use in source and binary forms, with or without
  103. # modification, are permitted provided that the following conditions
  104. # are met:
  105. #
  106. # 1. Redistributions of source code must retain the copyright
  107. # notice, this list of conditions and the following disclaimer.
  108. # 2. Redistributions in binary form must reproduce the copyright
  109. # notice, this list of conditions and the following disclaimer in the
  110. # documentation and/or other materials provided with the distribution.
  111. # 3. The name of the author may not be used to endorse or promote products
  112. # derived from this software without specific prior written permission.
  113. #
  114. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  115. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  116. # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  117. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  118. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  119. # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  120. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  121. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  122. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  123. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  124. include(CMakeParseArguments)
  125. macro(ecm_find_package_version_check module_name)
  126. if(CMAKE_VERSION VERSION_LESS 2.8.12)
  127. message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake")
  128. endif()
  129. if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
  130. message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Find${module_name}.cmake")
  131. endif()
  132. endmacro()
  133. macro(ecm_find_package_parse_components module_name)
  134. set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING)
  135. set(ecm_fppc_oneValueArgs RESULT_VAR)
  136. set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS)
  137. cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN})
  138. if(ECM_FPPC_UNPARSED_ARGUMENTS)
  139. message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}")
  140. endif()
  141. if(NOT ECM_FPPC_RESULT_VAR)
  142. message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components")
  143. endif()
  144. if(NOT ECM_FPPC_KNOWN_COMPONENTS)
  145. message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components")
  146. endif()
  147. if(NOT ECM_FPPC_DEFAULT_COMPONENTS)
  148. set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS})
  149. endif()
  150. if(${module_name}_FIND_COMPONENTS)
  151. set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS})
  152. if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING)
  153. # Make sure deps are included
  154. foreach(ecm_fppc_comp ${ecm_fppc_requestedComps})
  155. foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps})
  156. list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index)
  157. if("${ecm_fppc_index}" STREQUAL "-1")
  158. if(NOT ${module_name}_FIND_QUIETLY)
  159. message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}")
  160. endif()
  161. list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}")
  162. endif()
  163. endforeach()
  164. endforeach()
  165. else()
  166. message(STATUS "Skipping dependency handling for ${module_name}")
  167. endif()
  168. list(REMOVE_DUPLICATES ecm_fppc_requestedComps)
  169. # This makes sure components are listed in the same order as
  170. # KNOWN_COMPONENTS (potentially important for inter-dependencies)
  171. set(${ECM_FPPC_RESULT_VAR})
  172. foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS})
  173. list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index)
  174. if(NOT "${ecm_fppc_index}" STREQUAL "-1")
  175. list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}")
  176. list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index})
  177. endif()
  178. endforeach()
  179. # if there are any left, they are unknown components
  180. if(ecm_fppc_requestedComps)
  181. set(ecm_fppc_msgType STATUS)
  182. if(${module_name}_FIND_REQUIRED)
  183. set(ecm_fppc_msgType FATAL_ERROR)
  184. endif()
  185. if(NOT ${module_name}_FIND_QUIETLY)
  186. message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}")
  187. endif()
  188. return()
  189. endif()
  190. else()
  191. set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS})
  192. endif()
  193. endmacro()
  194. macro(ecm_find_package_handle_library_components module_name)
  195. set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING)
  196. set(ecm_fpwc_oneValueArgs)
  197. set(ecm_fpwc_multiValueArgs COMPONENTS)
  198. cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN})
  199. if(ECM_FPWC_UNPARSED_ARGUMENTS)
  200. message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}")
  201. endif()
  202. if(NOT ECM_FPWC_COMPONENTS)
  203. message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components")
  204. endif()
  205. include(FindPackageHandleStandardArgs)
  206. find_package(PkgConfig)
  207. foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS})
  208. set(ecm_fpwc_dep_vars)
  209. set(ecm_fpwc_dep_targets)
  210. if(NOT SKIP_DEPENDENCY_HANDLING)
  211. foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps})
  212. list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND")
  213. list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}")
  214. endforeach()
  215. endif()
  216. if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config)
  217. pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} QUIET
  218. ${${module_name}_${ecm_fpwc_comp}_pkg_config})
  219. endif()
  220. find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
  221. NAMES ${${module_name}_${ecm_fpwc_comp}_header}
  222. HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS}
  223. PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir}
  224. )
  225. find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY
  226. NAMES ${${module_name}_${ecm_fpwc_comp}_lib}
  227. HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS}
  228. )
  229. set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}")
  230. if(NOT ${module_name}_VERSION)
  231. set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION})
  232. endif()
  233. find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp}
  234. FOUND_VAR
  235. ${module_name}_${ecm_fpwc_comp}_FOUND
  236. REQUIRED_VARS
  237. ${module_name}_${ecm_fpwc_comp}_LIBRARY
  238. ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
  239. ${ecm_fpwc_dep_vars}
  240. VERSION_VAR
  241. ${module_name}_${ecm_fpwc_comp}_VERSION
  242. )
  243. mark_as_advanced(
  244. ${module_name}_${ecm_fpwc_comp}_LIBRARY
  245. ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
  246. )
  247. if(${module_name}_${ecm_fpwc_comp}_FOUND)
  248. list(APPEND ${module_name}_LIBRARIES
  249. "${${module_name}_${ecm_fpwc_comp}_LIBRARY}")
  250. list(APPEND ${module_name}_INCLUDE_DIRS
  251. "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}")
  252. set(${module_name}_DEFINITIONS
  253. ${${module_name}_DEFINITIONS}
  254. ${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS})
  255. if(NOT TARGET ${module_name}::${ecm_fpwc_comp})
  256. add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED)
  257. set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES
  258. IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}"
  259. INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}"
  260. INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}"
  261. INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}"
  262. )
  263. endif()
  264. list(APPEND ${module_name}_TARGETS
  265. "${module_name}::${ecm_fpwc_comp}")
  266. endif()
  267. endforeach()
  268. if(${module_name}_LIBRARIES)
  269. list(REMOVE_DUPLICATES ${module_name}_LIBRARIES)
  270. endif()
  271. if(${module_name}_INCLUDE_DIRS)
  272. list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS)
  273. endif()
  274. if(${module_name}_DEFINITIONS)
  275. list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS)
  276. endif()
  277. if(${module_name}_TARGETS)
  278. list(REMOVE_DUPLICATES ${module_name}_TARGETS)
  279. endif()
  280. endmacro()