Changeset View
Changeset View
Standalone View
Standalone View
modules/ECMAddQch.cmake
- This file was added.
1 | #.rst: | ||||
---|---|---|---|---|---|
2 | # ECMAddQch | ||||
3 | # ------------------ | ||||
4 | # | ||||
5 | # This module provides the ``ecm_add_qch`` function for generating API | ||||
6 | # documentation files in the QCH format, and the ``ecm_install_qch_export`` | ||||
7 | # function for generating and installing exported CMake targets for such | ||||
8 | # generated QCH files to enable builds of other software with generation of | ||||
9 | # QCH files to create links into the given QCH files. | ||||
10 | # | ||||
11 | # :: | ||||
12 | # | ||||
13 | # ecm_add_qch(<target_name> | ||||
14 | # NAME <name> | ||||
15 | # VERSION <version> | ||||
16 | # QCH_INSTALL_DESTINATION <qchfile_install_path> | ||||
17 | # TAGFILE_INSTALL_DESTINATION <tagsfile_install_path> | ||||
18 | # [BASE_NAME <basename>] | ||||
19 | # [SOURCE_DIRS <dir> [<dir2> [...]]] | ||||
20 | # [SOURCES <file> [<file2> [...]]] | ||||
21 | # |MD_MAINPAGE <md_file>] | ||||
22 | # [IMAGE_DIRS <idir> [<idir2> [...]]] | ||||
23 | # [EXAMPLE_DIRS <edir> [<edir2> [...]]] | ||||
24 | # [ORG_DOMAIN <domain>] | ||||
25 | # [NAMESPACE <namespace>] | ||||
26 | # [LINK_QCHS <qch> [<qch2> [...]]] | ||||
27 | # [BLANK_MACROS <macro> [<macro2> [...]]] | ||||
28 | # [CONFIG_TEMPLATE <configtemplate_file>] | ||||
29 | # [VERBOSE] | ||||
30 | # ) | ||||
31 | # | ||||
32 | # This macro adds a target called <target_name> for the creation of an API | ||||
33 | # documentation manual in the QCH format from the given sources. | ||||
34 | # It currently uses doxygen, future versions might optionally also allow other | ||||
35 | # tools. | ||||
36 | # Next to the QCH file the target will generate a corresponding doxygen tag | ||||
37 | # file, which enables creating links from other documentation into the | ||||
38 | # generated QCH file. | ||||
39 | # | ||||
40 | # If the required tools are not found, the macro will skip creation of the | ||||
41 | # target and only emit a warning, so the use of the macro can be introduced | ||||
42 | # without requiring anyone to also have the needed tools present at that time. | ||||
43 | # This behaviour might change in future versions to result in a fail instead. | ||||
44 | # It is recommended to make the use of this macro optional, by depending | ||||
45 | # the call to ``ecm_add_qch`` on a CMake option being set, with a name like | ||||
46 | # ``BUILD_QCH`` and being TRUE by default. This will allow the developers to | ||||
47 | # saves resources on normal source development build cycles by setting this | ||||
48 | # option to FALSE. | ||||
49 | # | ||||
50 | # The macro will set the target properties DOXYGEN_TAGFILE, QHP_NAMESPACE, | ||||
51 | # QHP_NAMESPACE_VERSIONED, QHP_VIRTUALFOLDER and LINK_QCHS to the respective | ||||
52 | # values, to allow other code access to them, e.g. the macro | ||||
53 | # ``ecm_install_qch_export``. | ||||
54 | # To enable the use of the target <target_name> as item for LINK_QCHS | ||||
55 | # in further ``ecm_add_qch`` calls in the current build, | ||||
56 | # additionally a target property DOXYGEN_TAGFILE_BUILD is set, with the path | ||||
57 | # of the created doxygen tag file in the build dir. | ||||
58 | # If existing, ``ecm_add_qch`` will use this property instead of | ||||
59 | # DOXYGEN_TAGFILE for access to the tags file. | ||||
60 | # | ||||
61 | # NAME specifies the name for the generated documentation. | ||||
62 | # | ||||
63 | # VERSION specifies the version of the library for which the documentation is | ||||
64 | # created. | ||||
65 | # | ||||
66 | # BASE_NAME specifies the base name for the generated files. | ||||
67 | # The default basename is ``<name>``. | ||||
68 | # | ||||
69 | # SOURCE_DIRS specifies the dirs (incl. subdirs) with the source files for | ||||
70 | # which the API documentation should be generated. Dirs can be relative to | ||||
71 | # the current source dir. Dependencies to the files in the dirs are not | ||||
72 | # tracked currently, other than with the SOURCES argument. So do not use for | ||||
73 | # sources generated during the build. | ||||
74 | # Needs to be used when SOURCES or CONFIG_TEMPLATE are not used. | ||||
75 | # | ||||
76 | # SOURCES specifies the source files for which the API documentation should be | ||||
77 | # generated. | ||||
78 | # Needs to be used when SOURCE_DIRS or CONFIG_TEMPLATE are not used. | ||||
79 | # | ||||
80 | # MD_MAINPAGE specifies a file in Markdown format that should be used as main | ||||
81 | # page. This page will overrule any ``\mainpage`` command in the included | ||||
82 | # sources. | ||||
83 | # | ||||
84 | # IMAGE_DIRS specifies the dirs which contain images that are included in the | ||||
85 | # documentation. Dirs can be relative to the current source dir. | ||||
86 | # | ||||
87 | # EXAMPLE_DIRS specifies the dirs which contain examples that are included in | ||||
88 | # the documentation. Dirs can be relative to the current source dir. | ||||
89 | # | ||||
90 | # QCH_INSTALL_DESTINATION specifies where the generated QCH file will be | ||||
91 | # installed. | ||||
92 | # | ||||
93 | # TAGFILE_INSTALL_DESTINATION specifies where the generated tag file will be | ||||
94 | # installed. | ||||
95 | # | ||||
96 | # NAMESPACE can be used to set a custom namespace <namespace> of the generated | ||||
97 | # QCH file. The namepspace is used as the unique id by QHelpEngine (cmp. | ||||
98 | # http://doc.qt.io/qt-5/qthelpproject.html#namespace). | ||||
99 | # The default namespace is ``<domain>.<name>``. | ||||
100 | # Needs to be used when ORG_DOMAIN is not used. | ||||
101 | # | ||||
102 | # ORG_DOMAIN can be used to define the organization domain prefix for the | ||||
103 | # default namespace of the generated QCH file. | ||||
104 | # Needs to be used when NAMESPACE is not used. | ||||
105 | # | ||||
106 | # LINK_QCHS specifies a list of other QCH targets which should be used for | ||||
107 | # creating references to API documenation of code in external libraries. | ||||
108 | # For each target <qch> in the list these target properties are expected to be | ||||
109 | # defined: DOXYGEN_TAGFILE, QHP_NAMESPACE and QHP_VIRTUALFOLDER. | ||||
110 | # If any of these is not existing, <qch> will be ignored. | ||||
111 | # Use the macro ``ecm_install_qch_export`` for exporting a target with these | ||||
112 | # properties with the CMake config of a library. | ||||
113 | # Any target <qch> can also be one created before in the same buildsystem by | ||||
114 | # another call of ``ecm_add_qch``. | ||||
115 | # | ||||
116 | # BLANK_MACROS specifies a list of C/C++ macro names which should be ignored by | ||||
117 | # the API dox generation tool and handled as if they resolve to empty strings. | ||||
118 | # Examples are export macros only defined in generated files, so whose | ||||
119 | # definition might be not available to the tool. | ||||
120 | # | ||||
121 | # CONFIG_TEMPLATE specifies a custom cmake template file for the config file | ||||
122 | # that is created to control the execution of the API dox generation tool. | ||||
123 | # The following CMake variables need to be used: | ||||
124 | # ECM_QCH_DOXYGEN_PERL_EXECUTABLE, ECM_QCH_DOXYGEN_QHELPGENERATOR_EXECUTABLE, | ||||
125 | # ECM_QCH_DOXYGEN_FILEPATH, ECM_QCH_DOXYGEN_TAGFILE. | ||||
126 | # The following CMake variables can be used: | ||||
127 | # ECM_QCH_DOXYGEN_PROJECTNAME, ECM_QCH_DOXYGEN_PROJECTVERSION, | ||||
128 | # ECM_QCH_DOXYGEN_VIRTUALFOLDER, ECM_QCH_DOXYGEN_FULLNAMESPACE, | ||||
129 | # ECM_QCH_DOXYGEN_TAGFILES, | ||||
130 | # ECM_QCH_DOXYGEN_WARN_LOGFILE, ECM_QCH_DOXYGEN_QUIET. | ||||
131 | # There is no guarantue that the other CMake variables currently used in the | ||||
132 | # default config file template will also be present with the same semantics | ||||
133 | # in future versions of this macro. | ||||
134 | # | ||||
135 | # VERBOSE tells the API dox generation tool to be more verbose about its | ||||
136 | # activity. | ||||
137 | # | ||||
138 | # Example usage: | ||||
139 | # | ||||
140 | # .. code-block:: cmake | ||||
141 | # | ||||
142 | # ecm_add_qch( | ||||
143 | # MyLib_QCH | ||||
144 | # NAME MyLib | ||||
145 | # VERSION "0.42.0" | ||||
146 | # ORG_DOMAIN org.myorg | ||||
147 | # SOURCE_DIRS | ||||
148 | # src | ||||
149 | # LINK_QCHS | ||||
150 | # Qt5Core_QCH | ||||
151 | # Qt5Xml_QCH | ||||
152 | # Qt5Gui_QCH | ||||
153 | # Qt5Widgets_QCH | ||||
154 | # BLANK_MACROS | ||||
155 | # MyLib_EXPORT | ||||
156 | # MyLib_DEPRECATED | ||||
157 | # TAGFILE_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/tags | ||||
158 | # QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/qch | ||||
159 | # ) | ||||
160 | # | ||||
161 | # Example usage (with two QCH files, second linking first): | ||||
162 | # | ||||
163 | # .. code-block:: cmake | ||||
164 | # | ||||
165 | # ecm_add_qch( | ||||
166 | # MyLib_QCH | ||||
167 | # NAME MyLib | ||||
168 | # VERSION ${MyLib_VERSION} | ||||
169 | # ORG_DOMAIN org.myorg | ||||
170 | # SOURCES ${MyLib_PUBLIC_HEADERS} | ||||
171 | # MD_MAINPAGE src/mylib/README.md | ||||
172 | # LINK_QCHS Qt5Core_QCH | ||||
173 | # TAGFILE_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/tags | ||||
174 | # QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/qch | ||||
175 | # ) | ||||
176 | # ecm_add_qch( | ||||
177 | # MyOtherLib_QCH | ||||
178 | # NAME MyOtherLib | ||||
179 | # VERSION ${MyOtherLib_VERSION} | ||||
180 | # ORG_DOMAIN org.myorg | ||||
181 | # SOURCES ${MyOtherLib_PUBLIC_HEADERS} | ||||
182 | # MD_MAINPAGE src/myotherlib/README.md | ||||
183 | # LINK_QCHS Qt5Core_QCH MyLib_QCH | ||||
184 | # TAGFILE_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/tags | ||||
185 | # QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/qch | ||||
186 | # ) | ||||
187 | # | ||||
188 | # :: | ||||
189 | # | ||||
190 | # ecm_install_qch_export( | ||||
191 | # TARGETS [<name> [<name2> [...]]] | ||||
192 | # FILE <file> | ||||
193 | # DESTINATION <dest> | ||||
194 | # [COMPONENT <component>}] | ||||
195 | # ) | ||||
196 | # | ||||
197 | # This macro creates and installs a CMake file <file> which exports the given | ||||
198 | # QCH targets <name> etc., so they can be picked up by CMake-based builds of | ||||
199 | # other software that also generate QCH files (using ``ecm_add_qch``) and | ||||
200 | # which should include links to the QCH files created by the given targets. | ||||
201 | # The installed CMake file <file> is expected to be included by the CMake | ||||
202 | # config file created for the software the related QCH files are documenting. | ||||
203 | # | ||||
204 | # TARGETS specifies the QCH targets which should be exported. If a target does | ||||
205 | # not exist or does not have all needed properties, a warning will be | ||||
206 | # generated and the target skipped. | ||||
207 | # This behaviour might change in future versions to result in a fail instead. | ||||
208 | # | ||||
209 | # FILE specifies the name of the created CMake file, typically with a .cmake | ||||
210 | # extension. | ||||
211 | # | ||||
212 | # DESTINATION specifies the directory on disk to which the file will be | ||||
213 | # installed. It usually is the same as the one where the CMake config files | ||||
214 | # for this software are installed. | ||||
215 | # | ||||
216 | # COMPONENT specifies the the installation component name with which the | ||||
217 | # install rule is associated. | ||||
218 | # | ||||
219 | # Example usage: | ||||
220 | # | ||||
221 | # .. code-block:: cmake | ||||
222 | # | ||||
223 | # ecm_install_qch_export( | ||||
224 | # TARGETS MyLib_QCH | ||||
225 | # FILE MyLibQCHTargets.cmake | ||||
226 | # DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/MyLib" | ||||
227 | # COMPONENT Devel | ||||
228 | # ) | ||||
229 | # | ||||
230 | # Since 5.30.0. | ||||
231 | | ||||
232 | #============================================================================= | ||||
233 | # Copyright 2016 Friedrich W. H. Kossebau <kossebau@kde.org> | ||||
234 | # | ||||
235 | # Redistribution and use in source and binary forms, with or without | ||||
236 | # modification, are permitted provided that the following conditions | ||||
237 | # are met: | ||||
238 | # | ||||
239 | # 1. Redistributions of source code must retain the copyright | ||||
240 | # notice, this list of conditions and the following disclaimer. | ||||
241 | # 2. Redistributions in binary form must reproduce the copyright | ||||
242 | # notice, this list of conditions and the following disclaimer in the | ||||
243 | # documentation and/or other materials provided with the distribution. | ||||
244 | # 3. The name of the author may not be used to endorse or promote products | ||||
245 | # derived from this software without specific prior written permission. | ||||
246 | # | ||||
247 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||
248 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||
249 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
250 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
251 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
252 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
253 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
254 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
255 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
256 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
257 | | ||||
258 | include(CMakeParseArguments) | ||||
259 | include(ECMQueryQmake) | ||||
260 | | ||||
261 | | ||||
262 | # Helper method: adding the LINK_QCHS property to a Qt QCH targets, from module base names ("Core" etc.) | ||||
263 | macro(_ecm_setup_qt_qch_links _module) | ||||
264 | set(_linkqchs) | ||||
265 | foreach(_linkqch ${ARGN}) | ||||
266 | list(APPEND _linkqchs "Qt5${_linkqch}_QCH") | ||||
267 | endforeach() | ||||
268 | set_property(TARGET Qt5${_module}_QCH PROPERTY LINK_QCHS ${_linkqchs}) | ||||
269 | endmacro() | ||||
270 | | ||||
271 | # Helper method: ensure Qt QCH targets are created | ||||
272 | function(_ecm_ensure_qt_qch_targets) | ||||
273 | # create QCH targets for Qt | ||||
274 | # Ideally one day Qt CMake Config files provide these | ||||
275 | if(NOT TARGET Qt5Core_QCH) | ||||
276 | # get Qt version, if any | ||||
277 | find_package(Qt5Core CONFIG QUIET) | ||||
278 | # lookup tag files | ||||
279 | query_qmake(qt_docs_dir QT_INSTALL_DOCS) | ||||
280 | find_path(_qtcoreTagsPath qtcore/qtcore.tags | ||||
281 | PATHS | ||||
282 | ${qt_docs_dir} | ||||
283 | ) | ||||
284 | | ||||
285 | if(Qt5Core_FOUND AND _qtcoreTagsPath) | ||||
286 | string(REPLACE "." "" _version ${Qt5Core_VERSION}) | ||||
287 | # TODO: properly find each tag file | ||||
288 | # TODO: complete list of Qt modules | ||||
289 | foreach(_module | ||||
290 | 3D Bluetooth Concurrent Core DBus Gui Location | ||||
291 | Network Positioning PrintSupport Qml Quick Sensors SerialPort Sql Svg | ||||
292 | WebChannel WebEngine WebSockets Widgets Xml XmlPatterns | ||||
293 | ) | ||||
294 | string(TOLOWER ${_module} _lowermodule) | ||||
295 | | ||||
296 | add_custom_target(Qt5${_module}_QCH) | ||||
297 | set_target_properties(Qt5${_module}_QCH PROPERTIES | ||||
298 | DOXYGEN_TAGFILE "${_qtcoreTagsPath}/qt${_lowermodule}/qt${_lowermodule}.tags" | ||||
299 | QHP_NAMESPACE "org.qt-project.qt${_lowermodule}" | ||||
300 | QHP_NAMESPACE_VERSIONED "org.qt-project.qt${_lowermodule}.${_version}" | ||||
301 | QHP_VIRTUALFOLDER "qt${_lowermodule}" | ||||
302 | IMPORTED TRUE | ||||
303 | ) | ||||
304 | endforeach() | ||||
305 | _ecm_setup_qt_qch_links(3D Gui Core) | ||||
306 | _ecm_setup_qt_qch_links(Bluetooth DBus Core) | ||||
307 | _ecm_setup_qt_qch_links(Concurrent Gui Core) | ||||
308 | _ecm_setup_qt_qch_links(DBus Core) | ||||
309 | _ecm_setup_qt_qch_links(Gui Core) | ||||
310 | _ecm_setup_qt_qch_links(Location Positioning Gui Core) | ||||
311 | _ecm_setup_qt_qch_links(Network Core) | ||||
312 | _ecm_setup_qt_qch_links(Positioning Core) | ||||
313 | _ecm_setup_qt_qch_links(PrintSupport Widgets Gui Core) | ||||
314 | _ecm_setup_qt_qch_links(Qml Network Core) | ||||
315 | _ecm_setup_qt_qch_links(Quick Qml Network Gui Core) | ||||
316 | _ecm_setup_qt_qch_links(Sensors Core) | ||||
317 | _ecm_setup_qt_qch_links(SerialPort Core) | ||||
318 | _ecm_setup_qt_qch_links(Sql Core) | ||||
319 | _ecm_setup_qt_qch_links(Svg Widgets Gui Core) | ||||
320 | _ecm_setup_qt_qch_links(WebChannel Qml Core) | ||||
321 | _ecm_setup_qt_qch_links(WebEngine Quick Qml Gui Core) | ||||
322 | _ecm_setup_qt_qch_links(WebSockets Network Core) | ||||
323 | _ecm_setup_qt_qch_links(Widgets Gui Core) | ||||
324 | _ecm_setup_qt_qch_links(Xml Core) | ||||
325 | _ecm_setup_qt_qch_links(XmlPatterns Network Core) | ||||
326 | endif() | ||||
327 | endif() | ||||
328 | endfunction() | ||||
329 | | ||||
330 | # Helper method: collect all qch targets from the LINK_QCHS dependency tree and set result to <var> | ||||
331 | function(_ecm_collect_linkable_qch_targets name) | ||||
332 | set(_candidate_qchs ${ARGN}) | ||||
333 | set(_handled_qchs) | ||||
334 | set(_good_qchs) | ||||
335 | # while unhandled qch targets | ||||
336 | while(_candidate_qchs) | ||||
337 | # get another unhandled qch target | ||||
338 | list(GET _candidate_qchs 0 _qch) | ||||
339 | list(REMOVE_AT _candidate_qchs 0) | ||||
340 | list(FIND _handled_qchs ${_qch} _index) | ||||
341 | # if not already handled | ||||
342 | if(_index EQUAL -1) | ||||
343 | list(APPEND _handled_qchs ${_qch}) | ||||
344 | if(TARGET ${_qch}) | ||||
345 | # always look at other linked qch targets, also for incomplete targets | ||||
346 | get_property(_link_qchs TARGET ${_qch} PROPERTY LINK_QCHS) | ||||
347 | if(_link_qchs) | ||||
348 | list(APPEND _candidate_qchs ${_link_qchs}) | ||||
349 | endif() | ||||
350 | # check if this target has all needed properties | ||||
351 | set(_target_usable TRUE) | ||||
352 | foreach(_propertyname | ||||
353 | DOXYGEN_TAGFILE | ||||
354 | QHP_NAMESPACE | ||||
355 | QHP_VIRTUALFOLDER | ||||
356 | ) | ||||
357 | get_target_property(_property ${_qch} ${_propertyname}) | ||||
358 | if(NOT _property) | ||||
359 | message(STATUS "No property ${_propertyname} set on ${_qch} when calling ecm_add_qch(). <<${_property}>>") | ||||
360 | set(_target_usable FALSE) | ||||
361 | endif() | ||||
362 | endforeach() | ||||
363 | if(_target_usable) | ||||
364 | list(APPEND _good_qchs ${_qch}) | ||||
365 | else() | ||||
366 | message(WARNING "No linking to API dox of ${_qch}.") | ||||
367 | endif() | ||||
368 | else() | ||||
369 | message(STATUS "No such target ${_qch} defined when calling ecm_add_qch(), ignored.") | ||||
370 | endif() | ||||
371 | endif() | ||||
372 | endwhile() | ||||
373 | set(${name} ${_good_qchs} PARENT_SCOPE) | ||||
374 | endfunction() | ||||
375 | | ||||
376 | | ||||
377 | function(ecm_add_qch target_name) | ||||
378 | # Parse arguments | ||||
379 | set(options VERBOSE) | ||||
380 | set(oneValueArgs NAME BASE_NAME QCH_INSTALL_DESTINATION TAGFILE_INSTALL_DESTINATION VERSION NAMESPACE MD_MAINPAGE ORG_DOMAIN CONFIG_TEMPLATE) | ||||
381 | set(multiValueArgs SOURCE_DIRS SOURCES IMAGE_DIRS EXAMPLE_DIRS BLANK_MACROS LINK_QCHS) | ||||
382 | cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | ||||
383 | | ||||
384 | # check required args | ||||
385 | foreach(_arg_name NAME QCH_INSTALL_DESTINATION TAGFILE_INSTALL_DESTINATION VERSION) | ||||
386 | if(NOT DEFINED ARGS_${_arg_name}) | ||||
387 | message(FATAL_ERROR "${_arg_name} needs to be defined when calling ecm_add_qch") | ||||
388 | endif() | ||||
389 | endforeach() | ||||
390 | if(NOT DEFINED ARGS_SOURCE_DIRS AND NOT DEFINED ARGS_SOURCES AND NOT DEFINED ARGS_CONFIG_TEMPLATE) | ||||
391 | message(FATAL_ERROR "SOURCE_DIRS or SOURCES needs to be defined when calling ecm_add_qch") | ||||
392 | endif() | ||||
393 | if(DEFINED ARGS_SOURCE_DIRS AND DEFINED ARGS_SOURCES) | ||||
394 | message(FATAL_ERROR "Either SOURCE_DIRS or SOURCES, not both, needs to be defined when calling ecm_add_qch") | ||||
395 | endif() | ||||
396 | if(NOT DEFINED ARGS_ORG_DOMAIN AND NOT DEFINED ARGS_NAMESPACE) | ||||
397 | message(FATAL_ERROR "ORG_DOMAIN or NAMESPACE needs to be defined when calling ecm_add_qch") | ||||
398 | endif() | ||||
399 | | ||||
400 | # find required tools | ||||
401 | # TODO: check with doxygen author if perl is really still required, PERL_PATH seems unused in doxygen | ||||
402 | find_package(Perl) | ||||
403 | set_package_properties(Perl PROPERTIES | ||||
404 | PURPOSE "Needed for API dox QCH file generation" | ||||
405 | TYPE OPTIONAL | ||||
406 | ) | ||||
407 | if (NOT DOXYGEN_PATCHED_JSFILESADDED) | ||||
408 | set(REQUIRED_DOXYGEN_VERSION 1.8.13) | ||||
409 | endif() | ||||
410 | find_package(Doxygen ${REQUIRED_DOXYGEN_VERSION}) | ||||
411 | if (NOT DOXYGEN_FOUND AND NOT DOXYGEN_PATCHED_JSFILESADDED) | ||||
412 | set(doxygen_description_addition " (Or older version patched with https://github.com/doxygen/doxygen/commit/bf9415698e53d79b, pass -DDOXYGEN_PATCHED_JSFILESADDED=ON to cmake if patched)") | ||||
413 | endif() | ||||
414 | set_package_properties(Doxygen PROPERTIES | ||||
415 | TYPE OPTIONAL | ||||
416 | PURPOSE "Needed for API dox QCH file generation${doxygen_description_addition}" | ||||
417 | ) | ||||
418 | find_package(QHelpGenerator) | ||||
419 | set_package_properties(QHelpGenerator PROPERTIES | ||||
420 | TYPE OPTIONAL | ||||
421 | PURPOSE "Needed for API dox QCH file generation" | ||||
422 | DESCRIPTION "Part of Qt5 tools" | ||||
423 | ) | ||||
424 | set(_missing_tools) | ||||
425 | if (NOT PERL_FOUND) | ||||
426 | list(APPEND _missing_tools "Perl") | ||||
427 | endif() | ||||
428 | if (NOT DOXYGEN_FOUND) | ||||
429 | list(APPEND _missing_tools "Doxygen") | ||||
430 | endif() | ||||
431 | if (NOT QHelpGenerator_FOUND) | ||||
432 | list(APPEND _missing_tools "qhelpgenerator") | ||||
433 | endif() | ||||
434 | | ||||
435 | if (_missing_tools) | ||||
436 | message(WARNING "API dox QCH file will not be generated, tools missing: ${_missing_tools}!") | ||||
437 | else() | ||||
438 | _ecm_ensure_qt_qch_targets() | ||||
439 | | ||||
440 | # prepare base dirs, working file names and other vars | ||||
441 | if (DEFINED ARGS_BASE_NAME) | ||||
442 | set(_basename ${ARGS_BASE_NAME}) | ||||
443 | else() | ||||
444 | set(_basename ${ARGS_NAME}) | ||||
445 | endif() | ||||
446 | set(_qch_file_basename "${_basename}.qch") | ||||
447 | set(_tags_file_basename "${_basename}.tags") | ||||
448 | set(_qch_buildpath "${CMAKE_CURRENT_BINARY_DIR}/${_qch_file_basename}") | ||||
449 | set(_tags_buildpath "${CMAKE_CURRENT_BINARY_DIR}/${_tags_file_basename}") | ||||
450 | set(_apidox_builddir "${CMAKE_CURRENT_BINARY_DIR}/${_basename}_ECMQchDoxygen") | ||||
451 | if (DEFINED ARGS_NAMESPACE) | ||||
452 | set(_namespace "${ARGS_NAMESPACE}") | ||||
453 | else() | ||||
454 | set(_namespace "${ARGS_ORG_DOMAIN}.${ARGS_NAME}") | ||||
455 | endif() | ||||
456 | string(REPLACE "." "_" _dotLessVersion ${ARGS_VERSION}) | ||||
457 | set(_versioned_namespace "${_namespace}.${_dotLessVersion}") | ||||
458 | set(_sources) | ||||
459 | set(_dep_tagfiles) | ||||
460 | set(_dep_qch_targets) | ||||
461 | | ||||
462 | ### Create doxygen config file | ||||
463 | set(_doxygenconfig_file "${CMAKE_CURRENT_BINARY_DIR}/${_basename}_ECMQchDoxygen.config") | ||||
464 | if (DEFINED ARGS_CONFIG_TEMPLATE) | ||||
465 | set(_doxygenconfig_template_file "${ARGS_CONFIG_TEMPLATE}") | ||||
466 | else() | ||||
467 | set(_doxygenconfig_template_file "${ECM_MODULE_DIR}/ECMQchDoxygen.config.in") | ||||
468 | endif() | ||||
469 | # Setup variables used in config file template, ECM_QCH_DOXYGEN_* | ||||
470 | set(ECM_QCH_DOXYGEN_OUTPUTDIR "\"${_apidox_builddir}\"") | ||||
471 | set(ECM_QCH_DOXYGEN_TAGFILE "\"${_tags_buildpath}\"") | ||||
472 | set(ECM_QCH_DOXYGEN_LAYOUTFILE "\"${ECM_MODULE_DIR}/ECMQchDoxygenLayout.xml\"") | ||||
473 | set(ECM_QCH_DOXYGEN_IMAGEDIRS) | ||||
474 | foreach(_image_DIR IN LISTS ARGS_IMAGE_DIRS) | ||||
475 | if (NOT IS_ABSOLUTE ${_image_DIR}) | ||||
476 | set(_image_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_image_DIR}") | ||||
477 | endif() | ||||
478 | # concat dirs separated by a break, it is no issue that first has also a leading break | ||||
479 | set(ECM_QCH_DOXYGEN_IMAGEDIRS "${ECM_QCH_DOXYGEN_IMAGEDIRS} \\\n\"${_image_DIR}\"") | ||||
480 | endforeach() | ||||
481 | set(ECM_QCH_DOXYGEN_EXAMPLEDIRS) | ||||
482 | foreach(_example_DIR IN LISTS ARGS_EXAMPLE_DIRS) | ||||
483 | if (NOT IS_ABSOLUTE ${_example_DIR}) | ||||
484 | set(_example_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_example_DIR}") | ||||
485 | endif() | ||||
486 | # concat dirs separated by a break, it is no issue that first has also a leading break | ||||
487 | set(ECM_QCH_DOXYGEN_EXAMPLEDIRS "${ECM_QCH_DOXYGEN_EXAMPLEDIRS} \\\n\"${_example_DIR}\"") | ||||
488 | endforeach() | ||||
489 | if (ARGS_MD_MAINPAGE) | ||||
490 | if (NOT IS_ABSOLUTE ${ARGS_MD_MAINPAGE}) | ||||
491 | set(ARGS_MD_MAINPAGE "${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_MD_MAINPAGE}") | ||||
492 | endif() | ||||
493 | set(ECM_QCH_DOXYGEN_MAINPAGE_MDFILE "\"${ARGS_MD_MAINPAGE}\"") | ||||
494 | else() | ||||
495 | set(ECM_QCH_DOXYGEN_MAINPAGE_MDFILE) | ||||
496 | endif() | ||||
497 | set(ECM_QCH_DOXYGEN_INPUT) | ||||
498 | if (ARGS_SOURCE_DIRS) | ||||
499 | foreach(_source_DIR IN LISTS ARGS_SOURCE_DIRS) | ||||
500 | if (NOT IS_ABSOLUTE ${_source_DIR}) | ||||
501 | set(_source_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_source_DIR}") | ||||
502 | endif() | ||||
503 | # concat dirs separated by a break, it is no issue that first has also a leading break | ||||
504 | set(ECM_QCH_DOXYGEN_INPUT "${ECM_QCH_DOXYGEN_INPUT} \\\n\"${_source_DIR}\"") | ||||
505 | endforeach() | ||||
506 | if (ARGS_MD_MAINPAGE) | ||||
507 | set(ECM_QCH_DOXYGEN_INPUT "${ECM_QCH_DOXYGEN_INPUT} \\\n\"${ARGS_MD_MAINPAGE}\"") | ||||
508 | endif() | ||||
509 | set(ECM_QCH_DOXYGEN_FILE_PATTERNS "*.h *.cpp *.hpp *.hh *.cc *.h++ *.c++ *.hxx *.cxx *.dox *.md") | ||||
510 | else() | ||||
511 | foreach(_source IN LISTS ARGS_SOURCES) | ||||
512 | if (NOT IS_ABSOLUTE ${_source}) | ||||
513 | set(_source "${CMAKE_CURRENT_SOURCE_DIR}/${_source}") | ||||
514 | endif() | ||||
515 | list(APPEND _sources "${_source}") | ||||
516 | endforeach() | ||||
517 | if (ARGS_MD_MAINPAGE) | ||||
518 | list(FIND _sources ${ARGS_MD_MAINPAGE} _mainpage_index) | ||||
519 | if (_mainpage_index STREQUAL -1) | ||||
520 | list(APPEND _sources "${ARGS_MD_MAINPAGE}") | ||||
521 | endif() | ||||
522 | endif() | ||||
523 | foreach(_source IN LISTS _sources) | ||||
524 | # concat sources separated by a break, it is no issue that first has also a leading break | ||||
525 | set(ECM_QCH_DOXYGEN_INPUT "${ECM_QCH_DOXYGEN_INPUT} \\\n\"${_source}\"") | ||||
526 | endforeach() | ||||
527 | set(ECM_QCH_DOXYGEN_FILE_PATTERNS "") | ||||
528 | endif() | ||||
529 | | ||||
530 | set(ECM_QCH_DOXYGEN_PROJECTNAME ${ARGS_NAME}) | ||||
531 | file(RELATIVE_PATH _builddirrelative_filepath "${_apidox_builddir}/html" ${_qch_buildpath}) | ||||
532 | set(ECM_QCH_DOXYGEN_FILEPATH "\"${_builddirrelative_filepath}\"") | ||||
533 | set(ECM_QCH_DOXYGEN_PROJECTVERSION ${ARGS_VERSION}) | ||||
534 | string(TOLOWER ${ARGS_NAME} ECM_QCH_DOXYGEN_VIRTUALFOLDER) | ||||
535 | set(ECM_QCH_DOXYGEN_FULLNAMESPACE ${_versioned_namespace}) | ||||
536 | set(ECM_QCH_DOXYGEN_BLANK_MACROS) | ||||
537 | foreach(_macro IN LISTS ARGS_BLANK_MACROS) | ||||
538 | # concat dirs separated by a break, it is no issue that first has also a leading break | ||||
539 | set(ECM_QCH_DOXYGEN_BLANK_MACROS "${ECM_QCH_DOXYGEN_BLANK_MACROS} \\\n${_macro}=\"\"") | ||||
540 | endforeach() | ||||
541 | | ||||
542 | # create list of tag files for linking other QCH files | ||||
543 | set(ECM_QCH_DOXYGEN_TAGFILES) | ||||
544 | _ecm_collect_linkable_qch_targets(_link_qchs ${ARGS_LINK_QCHS}) | ||||
545 | foreach(_link_qch IN LISTS _link_qchs) | ||||
546 | list(APPEND _dep_qch_targets ${_link_qch}) | ||||
547 | get_target_property(_link_qch_tagfile ${_link_qch} DOXYGEN_TAGFILE) | ||||
548 | get_target_property(_link_qch_tagfile_build ${_link_qch} DOXYGEN_TAGFILE_BUILD) | ||||
549 | get_target_property(_link_qch_namespace ${_link_qch} QHP_NAMESPACE) | ||||
550 | get_target_property(_link_qch_virtualfolder ${_link_qch} QHP_VIRTUALFOLDER) | ||||
551 | # if same build, then prefer build version over any installed one | ||||
552 | if (_link_qch_tagfile_build) | ||||
553 | set(_link_qch_tagfile ${_link_qch_tagfile_build}) | ||||
554 | list(APPEND _dep_tagfiles "${_link_qch_tagfile}") | ||||
555 | endif() | ||||
556 | get_property(_linkqchs TARGET ${_link_qch} PROPERTY LINK_QCHS) | ||||
557 | set(_tagfile_entry "\"${_link_qch_tagfile}=qthelp://${_link_qch_namespace}/${_link_qch_virtualfolder}/\"") | ||||
558 | # concat dirs separated by a break, it is no issue that first has also a leading break | ||||
559 | set(ECM_QCH_DOXYGEN_TAGFILES "${ECM_QCH_DOXYGEN_TAGFILES} \\\n${_tagfile_entry}") | ||||
560 | endforeach() | ||||
561 | | ||||
562 | set(ECM_QCH_DOXYGEN_WARN_LOGFILE "\"${_doxygenconfig_file}.log\"") | ||||
563 | if(ARGS_VERBOSE) | ||||
564 | set(ECM_QCH_DOXYGEN_QUIET "NO") | ||||
565 | else() | ||||
566 | set(ECM_QCH_DOXYGEN_QUIET "YES") | ||||
567 | endif() | ||||
568 | set(ECM_QCH_DOXYGEN_PERL_EXECUTABLE "${PERL_EXECUTABLE}") | ||||
569 | set(ECM_QCH_DOXYGEN_QHELPGENERATOR_EXECUTABLE ${QHelpGenerator_EXECUTABLE}) | ||||
570 | | ||||
571 | # finally create doxygen config file | ||||
572 | configure_file( | ||||
573 | "${_doxygenconfig_template_file}" | ||||
574 | "${_doxygenconfig_file}" | ||||
575 | @ONLY | ||||
576 | ) | ||||
577 | | ||||
578 | # setup make target | ||||
579 | set(_qch_INSTALLPATH ${ARGS_QCH_INSTALL_DESTINATION}) | ||||
580 | set(_tags_INSTALLPATH ${ARGS_TAGFILE_INSTALL_DESTINATION}) | ||||
581 | file(RELATIVE_PATH _relative_qch_file ${CMAKE_BINARY_DIR} ${_qch_buildpath}) | ||||
582 | file(RELATIVE_PATH _relative_tags_file ${CMAKE_BINARY_DIR} ${_tags_buildpath}) | ||||
583 | add_custom_command( | ||||
584 | OUTPUT ${_qch_buildpath} ${_tags_buildpath} | ||||
585 | COMMENT "Generating ${_relative_qch_file}, ${_relative_tags_file}" | ||||
586 | COMMAND cmake -E remove_directory "${ECM_QCH_DOXYGEN_OUTPUTDIR}" | ||||
587 | COMMAND cmake -E make_directory "${ECM_QCH_DOXYGEN_OUTPUTDIR}" | ||||
588 | COMMAND ${DOXYGEN_EXECUTABLE} "${_doxygenconfig_file}" | ||||
589 | DEPENDS ${_doxygenconfig_file} ${_sources} ${_dep_tagfiles} ${_dep_qch_targets} | ||||
590 | ) | ||||
591 | add_custom_target(${target_name} ALL DEPENDS ${_qch_buildpath} ${_tags_buildpath}) | ||||
592 | set_target_properties(${target_name} PROPERTIES | ||||
593 | DOXYGEN_TAGFILE "${_qch_INSTALLPATH}/${_tags_file_basename}" | ||||
594 | DOXYGEN_TAGFILE_BUILD "${_tags_buildpath}" | ||||
595 | QHP_NAMESPACE "${_namespace}" | ||||
596 | QHP_NAMESPACE_VERSIONED "${_versioned_namespace}" | ||||
597 | QHP_VIRTUALFOLDER "${ECM_QCH_DOXYGEN_VIRTUALFOLDER}" | ||||
598 | ) | ||||
599 | # list as value does not work with set_target_properties | ||||
600 | set_property(TARGET ${target_name} PROPERTY LINK_QCHS "${ARGS_LINK_QCHS}") | ||||
601 | | ||||
602 | # setup installation | ||||
603 | install(FILES | ||||
604 | ${_qch_buildpath} | ||||
605 | DESTINATION ${_qch_INSTALLPATH} | ||||
606 | COMPONENT Devel | ||||
607 | ) | ||||
608 | | ||||
609 | install(FILES | ||||
610 | ${_tags_buildpath} | ||||
611 | DESTINATION ${_tags_INSTALLPATH} | ||||
612 | COMPONENT Devel | ||||
613 | ) | ||||
614 | endif() | ||||
615 | | ||||
616 | endfunction() | ||||
617 | | ||||
618 | | ||||
619 | function(ecm_install_qch_export) | ||||
620 | set(options ) | ||||
621 | set(oneValueArgs FILE DESTINATION COMPONENT) | ||||
622 | set(multiValueArgs TARGETS) | ||||
623 | | ||||
624 | cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | ||||
625 | | ||||
626 | if(NOT DEFINED ARGS_FILE) | ||||
627 | message(FATAL_ERROR "FILE needs to be defined when calling ecm_install_qch_export().") | ||||
628 | endif() | ||||
629 | | ||||
630 | if(NOT DEFINED ARGS_DESTINATION) | ||||
631 | message(FATAL_ERROR "DESTINATION needs to be defined when calling ecm_install_qch_export().") | ||||
632 | endif() | ||||
633 | | ||||
634 | # TARGETS may be empty (and ARGS_TARGETS will not be defined then by cmake_parse_arguments) | ||||
635 | | ||||
636 | set(_content | ||||
637 | "# Generated by ecm_install_qch_export() | ||||
638 | # Any changes to this file will be overwritten by the next CMake run. | ||||
639 | " | ||||
640 | ) | ||||
641 | | ||||
642 | foreach(_target IN LISTS ARGS_TARGETS) | ||||
643 | set(_target_usable TRUE) | ||||
644 | | ||||
645 | if (NOT TARGET ${_target}) | ||||
646 | message(STATUS "No such target ${_target} when calling ecm_install_qch_export().") | ||||
647 | set(_target_usable FALSE) | ||||
648 | else() | ||||
649 | foreach(_propertyname | ||||
650 | DOXYGEN_TAGFILE | ||||
651 | QHP_NAMESPACE | ||||
652 | QHP_NAMESPACE_VERSIONED | ||||
653 | QHP_VIRTUALFOLDER | ||||
654 | ) | ||||
655 | get_target_property(_property ${_target} ${_propertyname}) | ||||
656 | if(NOT _property) | ||||
657 | message(STATUS "No property ${_propertyname} set on ${_target} when calling ecm_install_qch_export(). <${_property}>") | ||||
658 | set(_target_usable FALSE) | ||||
659 | endif() | ||||
660 | endforeach() | ||||
661 | endif() | ||||
662 | if(_target_usable) | ||||
663 | get_target_property(_tagfile ${_target} DOXYGEN_TAGFILE) | ||||
664 | get_target_property(_namespace ${_target} QHP_NAMESPACE) | ||||
665 | get_target_property(_namespace_versioned ${_target} QHP_NAMESPACE_VERSIONED) | ||||
666 | get_target_property(_virtualfolder ${_target} QHP_VIRTUALFOLDER) | ||||
667 | get_property(_linkqchs TARGET ${_target} PROPERTY LINK_QCHS) | ||||
668 | set(_content "${_content} | ||||
669 | if (NOT TARGET ${_target}) | ||||
670 | | ||||
671 | add_custom_target(${_target}) | ||||
672 | set_target_properties(${_target} PROPERTIES | ||||
673 | DOXYGEN_TAGFILE \"${_tagfile}\" | ||||
674 | QHP_NAMESPACE \"${_namespace}\" | ||||
675 | QHP_NAMESPACE_VERSIONED \"${_namespace_versioned}\" | ||||
676 | QHP_VIRTUALFOLDER \"${_virtualfolder}\" | ||||
677 | IMPORTED TRUE | ||||
678 | ) | ||||
679 | set_property(TARGET ${_target} PROPERTY LINK_QCHS ${_linkqchs}) | ||||
680 | | ||||
681 | endif() | ||||
682 | " | ||||
683 | ) | ||||
684 | else() | ||||
685 | message(STATUS "No target exported for ${_target}.") | ||||
686 | endif() | ||||
687 | endforeach() | ||||
688 | | ||||
689 | if (NOT IS_ABSOLUTE ${ARGS_FILE}) | ||||
690 | set(ARGS_FILE "${CMAKE_CURRENT_BINARY_DIR}/${ARGS_FILE}") | ||||
691 | endif() | ||||
692 | | ||||
693 | file(GENERATE | ||||
694 | OUTPUT "${ARGS_FILE}" | ||||
695 | CONTENT "${_content}" | ||||
696 | ) | ||||
697 | | ||||
698 | if (DEFINED ARGS_COMPONENT) | ||||
699 | set(_component COMPONENT ${ARGS_COMPONENT}) | ||||
700 | endif() | ||||
701 | install( | ||||
702 | FILES "${ARGS_FILE}" | ||||
703 | DESTINATION "${ARGS_DESTINATION}" | ||||
704 | ${_component} | ||||
705 | ) | ||||
706 | | ||||
707 | endfunction() |