1ECM-DEVELOPER(7) Extra CMake Modules ECM-DEVELOPER(7)
2
3
4
6 ecm-developer - ECM Developer Reference
7
9 The CMake 3 documentation (and cmake-developer(7) in particular) has a
10 lot of useful information about writing CMake modules, including a
11 large section devoted to find modules. This guide will only highlight
12 things that are particular to the Extra CMake Modules project.
13
14 Most of these are stylistic points. For example, the license header for
15 a module in ECM should look like:
16
17 # SPDX-FileCopyrightText: 20XX Your Name <your.email@example.com>
18 #
19 # SPDX-License-Identifier: BSD-3-Clause
20
21 Documentation is written in reStructuredText format and put inside a
22 bracket comment with a .rst: id after the opening bracket:
23
24 #[=======================================================================[.rst:
25 The docs
26 #]=======================================================================]
27
28 (docs/sphinx/ext/ecm.py has code to extract the rst text from a comment
29 with such wrapping)
30
31 Functions should be used instead of macros unless there is a good rea‐
32 son not to (and that reason should be noted in a comment), and lower‐
33 case should be used for macros, functions and commands.
34
35 4 spaces is the generally-recommended indent, although there are sev‐
36 eral files that use 2 spaces; consistency within a file is more impor‐
37 tant than consistency across files.
38
39 If in doubt, look at how other modules in Extra CMake Modules are writ‐
40 ten, and follow the same pattern.
41
42 Find Modules
43 A good template for find module documentation is:
44
45 #[=======================================================================[.rst:
46 FindFoo
47 -------
48
49 Finds the Foo library.
50
51 This will define the following variables:
52
53 ``Foo_FOUND``
54 True if (the requested version of) Foo is available
55 ``Foo_VERSION``
56 The version of Foo, if it is found
57 ``Foo_LIBRARIES``
58 This can be passed to target_link_libraries() instead of the ``Foo::Foo``
59 target
60 ``Foo_INCLUDE_DIRS``
61 This should be passed to target_include_directories() if the target is not
62 used for linking
63 ``Foo_DEFINITIONS``
64 This should be passed to target_compile_options() if the target is not
65 used for linking
66
67 If ``Foo_FOUND`` is TRUE, it will also define the following imported target:
68
69 ``Foo::Foo``
70 The Foo library
71
72 In general we recommend using the imported target, as it is easier to use.
73 Bear in mind, however, that if the target is in the link interface of an
74 exported library, it must be made available by the package config file.
75 #]=======================================================================]
76
77 Note the use of definition lists for the variables.
78
79 Because of the ECMUseFindModules module, projects may easily make local
80 copies of find modules, and may install those copies with their own
81 CMake project config files. For this reason, find modules should in‐
82 clude the full BSD 3-clause license:
83
84 #=============================================================================
85 # Copyright 20XX Your Name <your.email@example.com>
86 #
87 # Redistribution and use in source and binary forms, with or without
88 # modification, are permitted provided that the following conditions
89 # are met:
90 #
91 # 1. Redistributions of source code must retain the copyright
92 # notice, this list of conditions and the following disclaimer.
93 # 2. Redistributions in binary form must reproduce the copyright
94 # notice, this list of conditions and the following disclaimer in the
95 # documentation and/or other materials provided with the distribution.
96 # 3. The name of the author may not be used to endorse or promote products
97 # derived from this software without specific prior written permission.
98 #
99 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
100 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
101 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
102 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
103 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
104 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
105 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
106 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
107 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
108 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
109 #=============================================================================
110
111 Find modules should always provide imported targets in addition to the
112 traditional variables (like Foo_LIBRARIES, etc).
113
114 Unlike find modules shipped with CMake, if the module requires a spe‐
115 cific CMake version it is not enough to warn when the minimum required
116 version is not high enough: you should also produce an error when the
117 actual CMake version being used is not high enough. This can be done
118 with:
119
120 if(CMAKE_VERSION VERSION_LESS 3.16.0)
121 message(FATAL_ERROR "CMake 3.16.0 is required by FindFoo.cmake")
122 endif()
123 if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.16.0)
124 message(AUTHOR_WARNING "Your project should require at least CMake 3.16.0 to use FindFoo.cmake")
125 endif()
126
127 The ECMFindModuleHelpers module has several useful functions and
128 macros. For example, it allows you to replace the above version check
129 with:
130
131 ecm_find_package_version_check(Foo)
132
133 Components
134 Using ECMFindModuleHelpers, creating a find module for a library with
135 several inter-dependent components is reasonably straightforward. After
136 the documentation, you need to include the module and do the usual ver‐
137 sion check:
138
139 include(ECMFindModuleHelpers)
140 ecm_find_package_version_check(Foo)
141
142 The important macros are ecm_find_package_parse_components and
143 ecm_find_package_handle_library_components. These take a list of com‐
144 ponents, and query other variables you provide to find out the informa‐
145 tion they require. The documentation for ECMFindModuleHelpers provides
146 more information, but a simple setup might look like:
147
148 set(Foo_known_components Bar Baz)
149 set(Foo_Bar_pkg_config "foo-bar")
150 set(Foo_Bar_lib "bar")
151 set(Foo_Bar_header "foo/bar.h")
152 set(Foo_Bar_pkg_config "foo-baz")
153 set(Foo_Baz_lib "baz")
154 set(Foo_Baz_header "foo/baz.h")
155
156 If Baz depends on Bar, for example, you can specify this with
157
158 set(Foo_Baz_component_deps "Bar")
159
160 Then call the macros:
161
162 ecm_find_package_parse_components(Foo
163 RESULT_VAR Foo_components
164 KNOWN_COMPONENTS ${Foo_known_components}
165 )
166 ecm_find_package_handle_library_components(Foo
167 COMPONENTS ${Foo_components}
168 )
169
170 Of course, if your components need unusual handling, you may want to
171 replace ecm_find_package_handle_library_components with, for example, a
172 foreach loop over the components (the body of which should implement
173 most of what a normal find module does, including setting Foo_<compo‐
174 nent>_FOUND).
175
176 At this point, you should set Foo_VERSION using whatever information
177 you have available (such as from parsing header files). Note that
178 ecm_find_package_handle_library_components will set it to the version
179 reported by pkg-config of the first component found, but this depends
180 on the presence of pkg-config files, and the version of a component may
181 not be the same as the version of the whole package. After that, fin‐
182 ish off with
183
184 include(FindPackageHandleStandardArgs)
185 find_package_handle_standard_args(Foo
186 FOUND_VAR
187 Foo_FOUND
188 REQUIRED_VARS
189 Foo_LIBRARIES
190 VERSION_VAR
191 Foo_VERSION
192 HANDLE_COMPONENTS
193 )
194
195 include(FeatureSummary)
196 set_package_properties(Foo PROPERTIES
197 URL "https://www.foo.example.com/"
198 DESCRIPTION "A library for doing useful things")
199
201 Proposed new modules should be submitted using the KDE Review Board in‐
202 stance, and be assigned to the buildsystem and extracmakemodules
203 groups. You should be able to point to two separate projects that will
204 make use of the module.
205
206 The mailing list can be found at
207 https://mail.kde.org/mailman/listinfo/kde-buildsystem.
208
210 KDE Developers
211
212
213
214
2155.111 Oct 14, 2023 ECM-DEVELOPER(7)