Warning, /frameworks/extra-cmake-modules/docs/manual/ecm-developer.7.rst is written in an unsupported language. File is not indexed.
0001 .. ecm-manual-description: ECM Developer Reference
0002
0003 ecm-developer(7)
0004 ****************
0005
0006 .. only:: html or latex
0007
0008 .. contents::
0009
0010
0011 Writing Modules
0012 ===============
0013
0014 The CMake 3 documentation (and `cmake-developer(7)`_ in particular) has a lot of
0015 useful information about writing CMake modules, including a large section
0016 devoted to find modules. This guide will only highlight things that are
0017 particular to the Extra CMake Modules project.
0018
0019 Most of these are stylistic points. For example, the license header for a module
0020 in ECM should look like:
0021
0022 .. code-block:: cmake
0023
0024 # SPDX-FileCopyrightText: 20XX Your Name <your.email@example.com>
0025 #
0026 # SPDX-License-Identifier: BSD-3-Clause
0027
0028 Documentation is written in reStructuredText format and put inside a bracket
0029 comment with a ``.rst:`` id after the opening bracket:
0030
0031 .. code-block:: cmake
0032
0033 #[=======================================================================[.rst:
0034 The docs
0035 #]=======================================================================]
0036
0037 (docs/sphinx/ext/ecm.py has code to extract the rst text from a comment with
0038 such wrapping)
0039
0040 Functions should be used instead of macros unless there is a good reason not to
0041 (and that reason should be noted in a comment), and lowercase should be used for
0042 macros, functions and commands.
0043
0044 4 spaces is the generally-recommended indent, although there are several files
0045 that use 2 spaces; consistency within a file is more important than consistency
0046 across files.
0047
0048 If in doubt, look at how other modules in Extra CMake Modules are written, and
0049 follow the same pattern.
0050
0051
0052 Find Modules
0053 ------------
0054
0055 A good template for find module documentation is:
0056
0057 .. code-block:: cmake
0058
0059 #[=======================================================================[.rst:
0060 FindFoo
0061 -------
0062
0063 Finds the Foo library.
0064
0065 This will define the following variables:
0066
0067 ``Foo_FOUND``
0068 True if (the requested version of) Foo is available
0069 ``Foo_VERSION``
0070 The version of Foo, if it is found
0071 ``Foo_LIBRARIES``
0072 This can be passed to target_link_libraries() instead of the ``Foo::Foo``
0073 target
0074 ``Foo_INCLUDE_DIRS``
0075 This should be passed to target_include_directories() if the target is not
0076 used for linking
0077 ``Foo_DEFINITIONS``
0078 This should be passed to target_compile_options() if the target is not
0079 used for linking
0080
0081 If ``Foo_FOUND`` is TRUE, it will also define the following imported target:
0082
0083 ``Foo::Foo``
0084 The Foo library
0085
0086 In general we recommend using the imported target, as it is easier to use.
0087 Bear in mind, however, that if the target is in the link interface of an
0088 exported library, it must be made available by the package config file.
0089 #]=======================================================================]
0090
0091 Note the use of definition lists for the variables.
0092
0093 Because of the :module:`ECMUseFindModules` module, projects may easily make
0094 local copies of find modules, and may install those copies with their own CMake
0095 project config files. For this reason, find modules should include the full BSD
0096 3-clause license::
0097
0098 #=============================================================================
0099 # Copyright 20XX Your Name <your.email@example.com>
0100 #
0101 # Redistribution and use in source and binary forms, with or without
0102 # modification, are permitted provided that the following conditions
0103 # are met:
0104 #
0105 # 1. Redistributions of source code must retain the copyright
0106 # notice, this list of conditions and the following disclaimer.
0107 # 2. Redistributions in binary form must reproduce the copyright
0108 # notice, this list of conditions and the following disclaimer in the
0109 # documentation and/or other materials provided with the distribution.
0110 # 3. The name of the author may not be used to endorse or promote products
0111 # derived from this software without specific prior written permission.
0112 #
0113 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0114 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0115 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0116 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0117 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0118 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0119 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0120 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0121 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0122 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0123 #=============================================================================
0124
0125 Find modules should always provide imported targets in addition to the
0126 traditional variables (like ``Foo_LIBRARIES``, etc).
0127
0128 Unlike find modules shipped with CMake, if the module requires a specific CMake
0129 version it is not enough to warn when the minimum required version is not high
0130 enough: you should also produce an error when the actual CMake version being
0131 used is not high enough. This can be done with:
0132
0133 .. code-block:: cmake
0134
0135 if(CMAKE_VERSION VERSION_LESS 3.16.0)
0136 message(FATAL_ERROR "CMake 3.16.0 is required by FindFoo.cmake")
0137 endif()
0138 if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.16.0)
0139 message(AUTHOR_WARNING "Your project should require at least CMake 3.16.0 to use FindFoo.cmake")
0140 endif()
0141
0142 The :module:`ECMFindModuleHelpers` module has several useful functions and
0143 macros. For example, it allows you to replace the above version check with:
0144
0145 .. code-block:: cmake
0146
0147 ecm_find_package_version_check(Foo)
0148
0149 Components
0150 ~~~~~~~~~~
0151
0152 Using :module:`ECMFindModuleHelpers`, creating a find module for a library with
0153 several inter-dependent components is reasonably straightforward. After the
0154 documentation, you need to include the module and do the usual version check:
0155
0156 .. code-block:: cmake
0157
0158 include(ECMFindModuleHelpers)
0159 ecm_find_package_version_check(Foo)
0160
0161 The important macros are ``ecm_find_package_parse_components`` and
0162 ``ecm_find_package_handle_library_components``. These take a list of
0163 components, and query other variables you provide to find out the information
0164 they require. The documentation for :module:`ECMFindModuleHelpers` provides
0165 more information, but a simple setup might look like:
0166
0167 .. code-block:: cmake
0168
0169 set(Foo_known_components Bar Baz)
0170 set(Foo_Bar_pkg_config "foo-bar")
0171 set(Foo_Bar_lib "bar")
0172 set(Foo_Bar_header "foo/bar.h")
0173 set(Foo_Bar_pkg_config "foo-baz")
0174 set(Foo_Baz_lib "baz")
0175 set(Foo_Baz_header "foo/baz.h")
0176
0177 If ``Baz`` depends on ``Bar``, for example, you can specify this with
0178
0179 .. code-block:: cmake
0180
0181 set(Foo_Baz_component_deps "Bar")
0182
0183 Then call the macros:
0184
0185 .. code-block:: cmake
0186
0187 ecm_find_package_parse_components(Foo
0188 RESULT_VAR Foo_components
0189 KNOWN_COMPONENTS ${Foo_known_components}
0190 )
0191 ecm_find_package_handle_library_components(Foo
0192 COMPONENTS ${Foo_components}
0193 )
0194
0195 Of course, if your components need unusual handling, you may want to replace
0196 ``ecm_find_package_handle_library_components`` with, for example, a ``foreach``
0197 loop over the components (the body of which should implement most of what a
0198 normal find module does, including setting ``Foo_<component>_FOUND``).
0199
0200 At this point, you should set ``Foo_VERSION`` using whatever information you
0201 have available (such as from parsing header files). Note that
0202 ``ecm_find_package_handle_library_components`` will set it to the version
0203 reported by pkg-config of the first component found, but this depends on the
0204 presence of pkg-config files, and the version of a component may not be the same
0205 as the version of the whole package. After that, finish off with
0206
0207 .. code-block:: cmake
0208
0209 include(FindPackageHandleStandardArgs)
0210 find_package_handle_standard_args(Foo
0211 FOUND_VAR
0212 Foo_FOUND
0213 REQUIRED_VARS
0214 Foo_LIBRARIES
0215 VERSION_VAR
0216 Foo_VERSION
0217 HANDLE_COMPONENTS
0218 )
0219
0220 include(FeatureSummary)
0221 set_package_properties(Foo PROPERTIES
0222 URL "https://www.foo.example.com/"
0223 DESCRIPTION "A library for doing useful things")
0224
0225
0226 Submitting Modules
0227 ==================
0228
0229 Proposed new modules should be submitted using the `KDE Review Board instance`_,
0230 and be assigned to the ``buildsystem`` and ``extracmakemodules`` groups. You
0231 should be able to point to two separate projects that will make use of the
0232 module.
0233
0234 The mailing list can be found at
0235 https://mail.kde.org/mailman/listinfo/kde-buildsystem\ .
0236
0237
0238 .. _KDE Review Board instance: https://git.reviewboard.kde.org/
0239 .. _cmake-developer(7): https://www.cmake.org/cmake/help/git-master/manual/cmake-developer.7.html