diff options
author | Alex Merry <alex.merry@kde.org> | 2014-03-06 23:01:18 +0000 |
---|---|---|
committer | Alex Merry <alex.merry@kde.org> | 2014-03-17 18:05:23 +0000 |
commit | f686ff75f6e76c5ec1c1a485bae907ca0e814d21 (patch) | |
tree | be6ac3ea8a65781a862a0be915a89ea890851e16 /docs | |
parent | 7a1bcb0bcf63018b42a297a4dcf122beabd9013c (diff) | |
download | extra-cmake-modules-f686ff75f6e76c5ec1c1a485bae907ca0e814d21.tar.gz extra-cmake-modules-f686ff75f6e76c5ec1c1a485bae907ca0e814d21.tar.bz2 |
Create ECMFindModuleHelpers module for common find-module code
This currently mostly contains macros for handling components;
FindWayland and FindXCB are ported to use this module, which comes with
various improvements for them.
REVIEW: 116653
Diffstat (limited to 'docs')
-rw-r--r-- | docs/writing-find-modules.md | 163 |
1 files changed, 43 insertions, 120 deletions
diff --git a/docs/writing-find-modules.md b/docs/writing-find-modules.md index 1ab6566f..2130a43a 100644 --- a/docs/writing-find-modules.md +++ b/docs/writing-find-modules.md @@ -197,7 +197,7 @@ download it. include(FeatureSummary) set_package_properties(Foo PROPERTIES - URL http://www.foo.example.com/ + URL "http://www.foo.example.com/" DESCRIPTION "A library for doing useful things") Most of the cache variables should be hidden in the `ccmake` interface unless @@ -225,146 +225,69 @@ Components ---------- If your find module has multiple components, such as a package that provides -multiple libraries, the following pattern can be helpful. First (after the -version checks), define what components are available: +multiple libraries, the ECMFindModulesHelpers module can do a lot of the work +for you. First, you need to include the module, and perform the version check. +ECMFindModuleHelpers provides its own version check macro, which specifies the +minimum required CMake version for the other macros in that module. - set(knownComponents - Bar - Baz - ) - -Determine which components we need to find. Note that `Foo_FIND_COMPONENTS` is -defined if `find_package` was passed the `COMPONENTS` option. - - if (Foo_FIND_COMPONENTS) - set(requiredComponents ${Foo_FIND_COMPONENTS}) - else() - set(requiredComponents ${knownComponents}) - endif() - -Translate component names into names to pass to `pkg-config`, and check for any -unknown components: - - unset(unknownComponents) - foreach(comp ${requiredComponents}) - list(FIND knownComponents ${comp} index) - if("${index}" STREQUAL "-1") - list(APPEND unknownComponents "${comp}") - endif() - endforeach() - - if(DEFINED unknownComponents) - set(msgType STATUS) - if(Foo_FIND_REQUIRED) - set(msgType FATAL_ERROR) - endif() - if(NOT Foo_FIND_QUIETLY) - message(${msgType} "Foo: requested unknown components ${unknownComponents}") - endif() - return() - endif() + include(ECMFindModuleHelpers) + ecm_find_package_version_check(Foo) -Now we create a macro to handle each component. The logic is very similar to -that of a Find module without components; in fact, most of it could be replaced -with `find_package` calls that use either other `Find*.cmake` files or -`*Config.make` files. +The important macros are `ecm_find_package_parse_components` and +`ecm_find_package_handle_library_components`. These take a list of components, +and query other variables you provide to find out the information they require. +The documentation for ECMFindModuleHelpers provides more information, but a +simple setup might look like - include(FindPackageHandleStandardArgs) - find_package(PkgConfig) + set(Foo_known_components Bar Baz) + set(Foo_Bar_pkg_config "foo-bar") + set(Foo_Bar_lib "bar") + set(Foo_Bar_header "foo/bar.h") + set(Foo_Bar_pkg_config "foo-baz") + set(Foo_Baz_lib "baz") + set(Foo_Baz_header "foo/baz.h") - macro(_foo_handle_component _comp) - set(_header) - set(_lib) - set(_pkgconfig_module) - if("${_comp}" STREQUAL "Bar") - set(_header "Foo/bar.h") - set(_lib "bar") - set(_pkgconfig_module "foo-bar") - elseif("${_comp}" STREQUAL "Baz") - set(_header "Foo/baz.h") - set(_lib "baz") - set(_pkgconfig_module "foo-baz") - endif() - - pkg_check_modules(PC_Foo_${_comp} QUIET ${_pkgconfig_module}) - - find_path(Foo_${_comp}_INCLUDE_DIR - NAMES ${_header} - HINTS ${PC_Foo_${_comp}_INCLUDE_DIRS} - ) - find_library(Foo_${_comp}_LIBRARY - NAMES ${_lib} - HINTS ${PC_Foo_${_comp}_LIBRARY_DIRS} - ) - set(Foo_${_comp}_DEFINITIONS ${Foo_${_comp}_CFLAGS_OTHER}) - - # compatibility variables - if(Foo_${_comp}_INCLUDE_DIR AND Foo_${_comp}_LIBRARY) - list(APPEND Foo_DEFINITIONS ${Foo_${_comp}_DEFINITIONS}) - list(APPEND Foo_INCLUDE_DIRS ${Foo_${_comp}_INCLUDE_DIR}) - list(APPEND Foo_LIBRARIES ${Foo_${_comp}_LIBRARY}) - endif() - - set(Foo_${_comp}_VERSION "${PC_Foo_${_comp}_VERSION}") - if(NOT Foo_VERSION) - set(Foo_VERSION ${Foo_${_comp}_VERSION}) - endif() - - find_package_handle_standard_args(Foo_${_comp} - FOUND_VAR - Foo_${_comp}_FOUND - REQUIRED_VARS - Foo_${_comp}_LIBRARY - Foo_${_comp}_INCLUDE_DIR - VERSION_VAR - Foo_${_comp}_VERSION - ) +If `Baz` depends on `Bar`, for example, you can specify this with - mark_as_advanced( - Foo_${_comp}_LIBRARY - Foo_${_comp}_INCLUDE_DIR - ) + set(Foo_Baz_component_deps "Bar") - if(Foo_${_comp}_FOUND AND NOT TARGET Foo::${_comp}) - add_library(Foo::${_comp} UNKNOWN IMPORTED) - set_target_properties(Foo::${_comp} PROPERTIES - IMPORTED_LOCATION "${Foo_${_comp}_LIBRARY}" - INTERFACE_COMPILE_OPTIONS "${Foo_${_comp}_DEFINITIONS}" - INTERFACE_INCLUDE_DIRECTORIES "${Foo_${_comp}_INCLUDE_DIR}" - ) - endif() - endmacro() +Then call the macros: -And finish off with everything else: + ecm_find_package_parse_components(Foo + RESULT_VAR Foo_components + KNOWN_COMPONENTS ${Foo_known_components} + ) + ecm_find_package_handle_library_components(Foo + COMPONENTS ${Foo_components} + ) - foreach(comp ${requiredComponents}) - _foo_handle_component(${comp}) - endforeach() +Of course, if your components need unusual handling, you may want to replace +`ecm_find_package_handle_library_components` with, for example, a `foreach` loop +over the components (the body of which should implement most of what a normal +find module does, including setting `Foo_<component>_FOUND`). - # compatibility variables - if (Foo_INCLUDE_DIRS) - list(REMOVE_DUPLICATES Foo_INCLUDE_DIRS) - endif() - if (Foo_DEFINITIONS) - list(REMOVE_DUPLICATES Foo_DEFINITIONS) - endif() - set(Foo_VERSION_STRING ${Foo_VERSION}) +At this point, you should set `Foo_VERSION` using whatever information you have +available (such as from parsing header files). Note that +`ecm_find_package_handle_library_components` will set it to the version reported +by pkg-config of the first component found, but this depends on the presence of +pkg-config files, and the version of a component may not be the same as the +version of the whole package. After that, finish off with + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Foo FOUND_VAR Foo_FOUND REQUIRED_VARS Foo_LIBRARIES - Foo_INCLUDE_DIRS VERSION_VAR Foo_VERSION HANDLE_COMPONENTS ) - + include(FeatureSummary) set_package_properties(Foo PROPERTIES - URL http://www.foo.example.com/ - DESCRIPTION "A set of libraries for doing useful things") + URL "http://www.foo.example.com/" + DESCRIPTION "A library for doing useful things") Other Macros |