aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFriedrich W. H. Kossebau <kossebau@kde.org>2016-12-05 19:11:07 +0100
committerFriedrich W. H. Kossebau <kossebau@kde.org>2017-06-05 00:16:46 +0200
commitc837f58d505bfbfedb39288b839a62a6e9f1d1bf (patch)
tree6edfe68e8517d3470a3ffa033c3a41967b67dd4f
parent5fa41ecd623da7f69061bc5091bd4a3006c9895b (diff)
downloadextra-cmake-modules-c837f58d505bfbfedb39288b839a62a6e9f1d1bf.tar.gz
extra-cmake-modules-c837f58d505bfbfedb39288b839a62a6e9f1d1bf.tar.bz2
New: ECMAddQch, for generating qch & doxygen tag files
Summary: Enables generation of QCH files during a normal build, for documenting the public API of a library. These macros are especially done with release builds in mind, so distributed packages (like from Linux distributions) can include QCH files matching the version of the library and will be also automatically updated on new versions of the libary. Next to that these macros also support linking between different QCH files, so a subclass from another library for which there also is a QCH file installed will be linked to the entry in that other QCH file. This inter-QCH linking is especially useful for libraries extending Qt, where many of the used types are from Qt libraries. The macros come with the needed information for Qt libraries prepared, so the used Qt libraries just need to be listed in the LINK_QCHS argument by target names, like Qt5Core_QCH or Qt5Widgets_QCH. This should be a nice supplement to online services like api.kde.org, like Qt's own QCH files are to doc.qt.io, While QCH files from an abstract POV could be seen similar to code libraries, being components with links to lookup symbols/entries in other QCH files, so the rules and code should be done with similar concepts, currently CMake's target system seems bound to executable code creation. So things like "file(EXPORT ...)" could sadly not be reused, as custom targets are not supported with that. Thus a custom macro had to be created for now. Also could I not find a way to use namespaces like KF5::, for more consistent target naming. The patch also adds two variables to KDEInstallDirs.cmake for controlling where the QCH (and respective doxygen tag files) are installed. The QTQCHDIR variant allows to install QCH files for Qt-extending libraries into the same folder where Qt's own QCH files are, so Qt Assistant & other QCH viewer pick up them automatically to add them to the default help file collection. The QCHDIR variant would provide a neutral, but central installation location. Neutral, as it never "pollutes" the Qt system dirs with files possibly unrelated to Qt-based development (e.g. when simply using qthelp tools for documentation), and central, to help with finding available QCH files for manually adding/loading them into a viewer, given there is no official way currently to register the availability of QCH files on installing. Open questions: a) target system for exporting/importing done in a sane way? Better name pattern for the QCH targets than xxx_QCH (see the targets created for Qt, like Qt5Core_QCH)? b) sharing metadata with kapidox Initially I placed these macros into the kapidox module, as this seems the logic place. And would match what kdoctools does for user manuals. Just, that would create a build dependency on kapidox which complicates usage a little. Having these macros in ECM delivers them with no extra effort needed. The data in metainfo.yaml is partially duplicated with the data feed into the macros. How to deduplicate that is still open. Especially with the need to not depend on external data sources like identify.kde.org. Issues: * doxygen versions before 1.8.13 are broken and miss to include some files with generated QCH (https://bugzilla.gnome.org/show_bug.cgi?id=773693) * Qt Assistant often only built with QTextBrowser, while doxygen uses lots of HTML5 (incl. hardcoded JavaScript) (https://bugzilla.gnome.org/show_bug.cgi?id=773715), needs e.g. distributions to use QtWebKit to work, upcoming Qt versions might soon also have QtWebEngine based help viewer (https://codereview.qt-project.org/#/c/111559/) * inter-QCH links do not work in KDevelop currently (see https://bugs.kde.org/show_bug.cgi?id=372747) if installed as separate QCH files More details/background info at https://frinring.wordpress.com/2016/09/27/adding-api-dox-generation-to-the-build-by-cmake-macros/ Tags: #frameworks, #build_system Differential Revision: https://phabricator.kde.org/D2854
-rw-r--r--docs/module/ECMAddQch.rst1
-rw-r--r--find-modules/FindQHelpGenerator.cmake75
-rw-r--r--kde-modules/KDEInstallDirs.cmake26
-rw-r--r--modules/ECMAddQch.cmake761
-rw-r--r--modules/ECMQchDoxygen.config.in239
-rw-r--r--modules/ECMQchDoxygenLayout.xml194
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/KDEInstallDirsTest/var_list.cmake2
8 files changed, 1295 insertions, 4 deletions
diff --git a/docs/module/ECMAddQch.rst b/docs/module/ECMAddQch.rst
new file mode 100644
index 00000000..19fd2fd3
--- /dev/null
+++ b/docs/module/ECMAddQch.rst
@@ -0,0 +1 @@
+.. ecm-module:: ../../modules/ECMAddQch.cmake
diff --git a/find-modules/FindQHelpGenerator.cmake b/find-modules/FindQHelpGenerator.cmake
new file mode 100644
index 00000000..3d55da11
--- /dev/null
+++ b/find-modules/FindQHelpGenerator.cmake
@@ -0,0 +1,75 @@
+# WARNING: FOR ECM-INTERNAL USE ONLY, DO NOT USE IN OWN PROJECTS
+# THIS FILE MIGHT DISAPPEAR IN FUTURE VERSIONS OF ECM.
+
+# Finds the Qt5 QHelpGenerator
+#
+# QHelpGenerator_FOUND - True if QHelpGenerator found.
+# QHelpGenerator_EXECUTABLE - Path to executable
+
+#=============================================================================
+# Copyright 2016 Friedrich W. H. Kossebau <kossebau@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+find_package(Qt5Core QUIET)
+if (TARGET Qt5::qhelpgenerator)
+ get_target_property(QHelpGenerator_EXECUTABLE Qt5::qhelpgenerator LOCATION)
+else()
+ # assume same folder as qmake executable
+ if (TARGET Qt5::qmake)
+ get_target_property(_qmake_EXECUTABLE Qt5::qmake LOCATION)
+ get_filename_component(_path ${_qmake_EXECUTABLE} DIRECTORY)
+ else()
+ set(_path)
+ endif()
+ # TODO: prevent that the Qt4 version is picked up
+ find_program(QHelpGenerator_EXECUTABLE
+ NAMES
+ qhelpgenerator-qt5
+ qhelpgenerator
+ PATH
+ ${_path}
+ )
+endif()
+mark_as_advanced(QHelpGenerator_EXECUTABLE)
+
+if(QHelpGenerator_EXECUTABLE)
+ set(QHelpGenerator_FOUND TRUE)
+else()
+ set(QHelpGenerator_FOUND FALSE)
+endif()
+
+if(QHelpGenerator_FOUND)
+ if(NOT QHelpGenerator_FIND_QUIETLY )
+ message( STATUS "Found QHelpGenerator executable: ${QHelpGenerator_EXECUTABLE}")
+ endif()
+else()
+ if(QHelpGenerator_FIND_REQUIRED)
+ message( FATAL_ERROR "Could not find QHelpGenerator executable" )
+ else()
+ message( STATUS "Optional QHelpGenerator executable was not found" )
+ endif()
+endif()
+
diff --git a/kde-modules/KDEInstallDirs.cmake b/kde-modules/KDEInstallDirs.cmake
index 7f5e4477..42e8db5c 100644
--- a/kde-modules/KDEInstallDirs.cmake
+++ b/kde-modules/KDEInstallDirs.cmake
@@ -90,7 +90,7 @@
# desktop wallpaper images (``DATAROOTDIR/wallpapers``)
# [``WALLPAPER_INSTALL_DIR``]
# ``APPDIR``
-# application desktop files (``DATAROOTDIR/applications``)
+# application desktop files (``DATAROOTDIR/applications``) Since 1.1.0.
# [``XDG_APPS_INSTALL_DIR``]
# ``DESKTOPDIR``
# desktop directories (``DATAROOTDIR/desktop-directories``)
@@ -100,6 +100,10 @@
# [``XDG_MIME_INSTALL_DIR``]
# ``METAINFODIR``
# AppStream component metadata files (``DATAROOTDIR/metainfo``)
+# ``QTQCHDIR``
+# documentation bundles in QCH format for Qt-extending libraries (``DATAROOTDIR/doc``) Since 5.36.0.
+# ``QCHDIR``
+# documentation bundles in QCH format (``DATAROOTDIR/doc/qch``) Since 5.36.0.
# ``MANDIR``
# man documentation (``DATAROOTDIR/man``) [``MAN_INSTALL_DIR``]
# ``INFODIR``
@@ -174,8 +178,8 @@
#
# Since pre-1.0.0.
#
-# NB: The variables starting ``KDE_INSTALL_`` are only available since 1.6.0.
-# The ``APPDIR`` install variable is available since 1.1.0.
+# NB: The variables starting ``KDE_INSTALL_`` are available since 1.6.0,
+# unless otherwise noted with the variable.
#=============================================================================
# Copyright 2014-2015 Alex Merry <alex.merry@kde.org>
@@ -448,7 +452,7 @@ if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS)
endif()
endif()
-option (KDE_INSTALL_USE_QT_SYS_PATHS "Install mkspecs files, Plugins and Imports to the Qt 5 install dir" "${_default_KDE_INSTALL_USE_QT_SYS_PATHS}")
+option (KDE_INSTALL_USE_QT_SYS_PATHS "Install mkspecs files, QCH files for Qt-based libs, Plugins and Imports to the Qt 5 install dir" "${_default_KDE_INSTALL_USE_QT_SYS_PATHS}")
if(KDE_INSTALL_USE_QT_SYS_PATHS)
# Qt-specific vars
query_qmake(qt_plugins_dir QT_INSTALL_PLUGINS)
@@ -520,6 +524,18 @@ if(NOT KDE_INSTALL_DIRS_NO_DEPRECATED)
set(KF5_DATA_INSTALL_DIR "${CMAKE_INSTALL_DATADIR_KF5}")
endif()
+# Qt-specific data vars
+if(KDE_INSTALL_USE_QT_SYS_PATHS)
+ query_qmake(qt_docs_dir QT_INSTALL_DOCS)
+
+ _define_absolute(QTQCHDIR ${qt_docs_dir}
+ "documentation bundles in QCH format for Qt-extending libraries")
+else()
+ _define_relative(QTQCHDIR DATAROOTDIR "doc/qch"
+ "documentation bundles in QCH format for Qt-extending libraries")
+endif()
+
+
# KDE Framework-specific things
_define_relative(DOCBUNDLEDIR DATAROOTDIR "doc/HTML"
"documentation bundles generated using kdoctools"
@@ -572,6 +588,8 @@ _define_relative(MIMEDIR DATAROOTDIR "mime/packages"
XDG_MIME_INSTALL_DIR)
_define_relative(METAINFODIR DATAROOTDIR "metainfo"
"AppStream component metadata")
+_define_relative(QCHDIR DATAROOTDIR "doc/qch"
+ "documentation bundles in QCH format")
_define_relative(MANDIR DATAROOTDIR "man"
"man documentation"
MAN_INSTALL_DIR)
diff --git a/modules/ECMAddQch.cmake b/modules/ECMAddQch.cmake
new file mode 100644
index 00000000..3e853cb9
--- /dev/null
+++ b/modules/ECMAddQch.cmake
@@ -0,0 +1,761 @@
+#.rst:
+# ECMAddQch
+# ------------------
+#
+# This module provides the ``ecm_add_qch`` function for generating API
+# documentation files in the QCH format, and the ``ecm_install_qch_export``
+# function for generating and installing exported CMake targets for such
+# generated QCH files to enable builds of other software with generation of
+# QCH files to create links into the given QCH files.
+#
+# ::
+#
+# ecm_add_qch(<target_name>
+# NAME <name>
+# VERSION <version>
+# QCH_INSTALL_DESTINATION <qchfile_install_path>
+# TAGFILE_INSTALL_DESTINATION <tagsfile_install_path>
+# [COMPONENT <component>]
+# [BASE_NAME <basename>]
+# [SOURCE_DIRS <dir> [<dir2> [...]]]
+# [SOURCES <file> [<file2> [...]]]
+# |MD_MAINPAGE <md_file>]
+# [IMAGE_DIRS <idir> [<idir2> [...]]]
+# [EXAMPLE_DIRS <edir> [<edir2> [...]]]
+# [ORG_DOMAIN <domain>]
+# [NAMESPACE <namespace>]
+# [LINK_QCHS <qch> [<qch2> [...]]]
+# [PREDEFINED_MACROS <macro[=content]> [<macro2[=content]> [...]]]
+# [BLANK_MACROS <macro> [<macro2> [...]]]
+# [CONFIG_TEMPLATE <configtemplate_file>]
+# [VERBOSE]
+# )
+#
+# This macro adds a target called <target_name> for the creation of an API
+# documentation manual in the QCH format from the given sources.
+# It currently uses doxygen, future versions might optionally also allow other
+# tools.
+# Next to the QCH file the target will generate a corresponding doxygen tag
+# file, which enables creating links from other documentation into the
+# generated QCH file.
+#
+# If the required tools are not found, the macro will skip creation of the
+# target and only emit a warning, so the use of the macro can be introduced
+# without requiring anyone to also have the needed tools present at that time.
+# This behaviour might change in future versions to result in a fail instead.
+# It is recommended to make the use of this macro optional, by depending
+# the call to ``ecm_add_qch`` on a CMake option being set, with a name like
+# ``BUILD_QCH`` and being TRUE by default. This will allow the developers to
+# saves resources on normal source development build cycles by setting this
+# option to FALSE.
+#
+# The macro will set the target properties DOXYGEN_TAGFILE, QHP_NAMESPACE,
+# QHP_NAMESPACE_VERSIONED, QHP_VIRTUALFOLDER and LINK_QCHS to the respective
+# values, to allow other code access to them, e.g. the macro
+# ``ecm_install_qch_export``.
+# To enable the use of the target <target_name> as item for LINK_QCHS
+# in further ``ecm_add_qch`` calls in the current build,
+# additionally a target property DOXYGEN_TAGFILE_BUILD is set, with the path
+# of the created doxygen tag file in the build dir.
+# If existing, ``ecm_add_qch`` will use this property instead of
+# DOXYGEN_TAGFILE for access to the tags file.
+#
+# NAME specifies the name for the generated documentation.
+#
+# VERSION specifies the version of the library for which the documentation is
+# created.
+#
+# BASE_NAME specifies the base name for the generated files.
+# The default basename is ``<name>``.
+#
+# SOURCE_DIRS specifies the dirs (incl. subdirs) with the source files for
+# which the API documentation should be generated. Dirs can be relative to
+# the current source dir. Dependencies to the files in the dirs are not
+# tracked currently, other than with the SOURCES argument. So do not use for
+# sources generated during the build.
+# Needs to be used when SOURCES or CONFIG_TEMPLATE are not used.
+#
+# SOURCES specifies the source files for which the API documentation should be
+# generated.
+# Needs to be used when SOURCE_DIRS or CONFIG_TEMPLATE are not used.
+#
+# MD_MAINPAGE specifies a file in Markdown format that should be used as main
+# page. This page will overrule any ``\mainpage`` command in the included
+# sources.
+#
+# IMAGE_DIRS specifies the dirs which contain images that are included in the
+# documentation. Dirs can be relative to the current source dir.
+#
+# EXAMPLE_DIRS specifies the dirs which contain examples that are included in
+# the documentation. Dirs can be relative to the current source dir.
+#
+# QCH_INSTALL_DESTINATION specifies where the generated QCH file will be
+# installed.
+#
+# TAGFILE_INSTALL_DESTINATION specifies where the generated tag file will be
+# installed.
+#
+# COMPONENT specifies the installation component name with which the install
+# rules for the generated QCH file and tag file are associated.
+#
+# NAMESPACE can be used to set a custom namespace <namespace> of the generated
+# QCH file. The namepspace is used as the unique id by QHelpEngine (cmp.
+# http://doc.qt.io/qt-5/qthelpproject.html#namespace).
+# The default namespace is ``<domain>.<name>``.
+# Needs to be used when ORG_DOMAIN is not used.
+#
+# ORG_DOMAIN can be used to define the organization domain prefix for the
+# default namespace of the generated QCH file.
+# Needs to be used when NAMESPACE is not used.
+#
+# LINK_QCHS specifies a list of other QCH targets which should be used for
+# creating references to API documenation of code in external libraries.
+# For each target <qch> in the list these target properties are expected to be
+# defined: DOXYGEN_TAGFILE, QHP_NAMESPACE and QHP_VIRTUALFOLDER.
+# If any of these is not existing, <qch> will be ignored.
+# Use the macro ``ecm_install_qch_export`` for exporting a target with these
+# properties with the CMake config of a library.
+# Any target <qch> can also be one created before in the same buildsystem by
+# another call of ``ecm_add_qch``.
+#
+# PREDEFINED_MACROS specifies a list of C/C++ macros which should be handled as
+# given by the API dox generation tool.
+# Examples are macros only defined in generated files, so whose
+# definition might be not available to the tool.
+#
+# BLANK_MACROS specifies a list of C/C++ macro names which should be ignored by
+# the API dox generation tool and handled as if they resolve to empty strings.
+# Examples are export macros only defined in generated files, so whose
+# definition might be not available to the tool.
+#
+# CONFIG_TEMPLATE specifies a custom cmake template file for the config file
+# that is created to control the execution of the API dox generation tool.
+# The following CMake variables need to be used:
+# ECM_QCH_DOXYGEN_PERL_EXECUTABLE, ECM_QCH_DOXYGEN_QHELPGENERATOR_EXECUTABLE,
+# ECM_QCH_DOXYGEN_FILEPATH, ECM_QCH_DOXYGEN_TAGFILE.
+# The following CMake variables can be used:
+# ECM_QCH_DOXYGEN_PROJECTNAME, ECM_QCH_DOXYGEN_PROJECTVERSION,
+# ECM_QCH_DOXYGEN_VIRTUALFOLDER, ECM_QCH_DOXYGEN_FULLNAMESPACE,
+# ECM_QCH_DOXYGEN_TAGFILES,
+# ECM_QCH_DOXYGEN_WARN_LOGFILE, ECM_QCH_DOXYGEN_QUIET.
+# There is no guarantue that the other CMake variables currently used in the
+# default config file template will also be present with the same semantics
+# in future versions of this macro.
+#
+# VERBOSE tells the API dox generation tool to be more verbose about its
+# activity.
+#
+# Example usage:
+#
+# .. code-block:: cmake
+#
+# ecm_add_qch(
+# MyLib_QCH
+# NAME MyLib
+# VERSION "0.42.0"
+# ORG_DOMAIN org.myorg
+# SOURCE_DIRS
+# src
+# LINK_QCHS
+# Qt5Core_QCH
+# Qt5Xml_QCH
+# Qt5Gui_QCH
+# Qt5Widgets_QCH
+# BLANK_MACROS
+# MyLib_EXPORT
+# MyLib_DEPRECATED
+# TAGFILE_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/tags
+# QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/qch
+# COMPONENT Devel
+# )
+#
+# Example usage (with two QCH files, second linking first):
+#
+# .. code-block:: cmake
+#
+# ecm_add_qch(
+# MyLib_QCH
+# NAME MyLib
+# VERSION ${MyLib_VERSION}
+# ORG_DOMAIN org.myorg
+# SOURCES ${MyLib_PUBLIC_HEADERS}
+# MD_MAINPAGE src/mylib/README.md
+# LINK_QCHS Qt5Core_QCH
+# TAGFILE_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/tags
+# QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/qch
+# COMPONENT Devel
+# )
+# ecm_add_qch(
+# MyOtherLib_QCH
+# NAME MyOtherLib
+# VERSION ${MyOtherLib_VERSION}
+# ORG_DOMAIN org.myorg
+# SOURCES ${MyOtherLib_PUBLIC_HEADERS}
+# MD_MAINPAGE src/myotherlib/README.md
+# LINK_QCHS Qt5Core_QCH MyLib_QCH
+# TAGFILE_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/tags
+# QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/docs/qch
+# COMPONENT Devel
+# )
+#
+# ::
+#
+# ecm_install_qch_export(
+# TARGETS [<name> [<name2> [...]]]
+# FILE <file>
+# DESTINATION <dest>
+# [COMPONENT <component>]
+# )
+#
+# This macro creates and installs a CMake file <file> which exports the given
+# QCH targets <name> etc., so they can be picked up by CMake-based builds of
+# other software that also generate QCH files (using ``ecm_add_qch``) and
+# which should include links to the QCH files created by the given targets.
+# The installed CMake file <file> is expected to be included by the CMake
+# config file created for the software the related QCH files are documenting.
+#
+# TARGETS specifies the QCH targets which should be exported. If a target does
+# not exist or does not have all needed properties, a warning will be
+# generated and the target skipped.
+# This behaviour might change in future versions to result in a fail instead.
+#
+# FILE specifies the name of the created CMake file, typically with a .cmake
+# extension.
+#
+# DESTINATION specifies the directory on disk to which the file will be
+# installed. It usually is the same as the one where the CMake config files
+# for this software are installed.
+#
+# COMPONENT specifies the the installation component name with which the
+# install rule is associated.
+#
+# Example usage:
+#
+# .. code-block:: cmake
+#
+# ecm_install_qch_export(
+# TARGETS MyLib_QCH
+# FILE MyLibQCHTargets.cmake
+# DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/MyLib"
+# COMPONENT Devel
+# )
+#
+# Since 5.36.0.
+
+#=============================================================================
+# Copyright 2016-2017 Friedrich W. H. Kossebau <kossebau@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include(CMakeParseArguments)
+include(ECMQueryQmake)
+
+
+# Helper method: adding the LINK_QCHS property to a Qt QCH targets, from module base names ("Core" etc.)
+# if target does not exist (e.g. because no tagsfile was found), this is a no-op
+macro(_ecm_setup_qt_qch_links _module)
+ set(_target "Qt5${_module}_QCH")
+ if(TARGET ${_target})
+ set(_linkqchs)
+ foreach(_linkqch ${ARGN})
+ list(APPEND _linkqchs "Qt5${_linkqch}_QCH")
+ endforeach()
+ set_property(TARGET ${_target} PROPERTY LINK_QCHS ${_linkqchs})
+ endif()
+endmacro()
+
+# Helper method: ensure Qt QCH targets are created
+function(_ecm_ensure_qt_qch_targets)
+ # create QCH targets for Qt
+ # Ideally one day Qt CMake Config files provide these
+ if(NOT TARGET Qt5Core_QCH)
+ # get Qt version, if any
+ find_package(Qt5Core CONFIG QUIET)
+ # lookup tag files
+ query_qmake(qt_docs_dir QT_INSTALL_DOCS)
+ find_path(_qtcoreTagsPath qtcore/qtcore.tags
+ PATHS
+ ${qt_docs_dir}
+ )
+
+ if(Qt5Core_FOUND AND _qtcoreTagsPath)
+ string(REPLACE "." "" _version ${Qt5Core_VERSION})
+ # TODO: properly find each tag file
+ # TODO: complete list of Qt modules
+ # qtdbus.tags file missing since 5.0, QTBUG-60933, extra handling?
+ foreach(_module
+ 3D Bluetooth Concurrent Core DBus Gui Location
+ Network Positioning PrintSupport Qml Quick Sensors SerialPort Sql Svg
+ WebChannel WebEngine WebSockets Widgets Xml XmlPatterns
+ )
+ string(TOLOWER ${_module} _lowermodule)
+
+ set(_tagfile "${_qtcoreTagsPath}/qt${_lowermodule}/qt${_lowermodule}.tags")
+ if(EXISTS "${_tagfile}")
+ add_custom_target(Qt5${_module}_QCH)
+ set_target_properties(Qt5${_module}_QCH PROPERTIES
+ DOXYGEN_TAGFILE "${_tagfile}"
+ QHP_NAMESPACE "org.qt-project.qt${_lowermodule}"
+ QHP_NAMESPACE_VERSIONED "org.qt-project.qt${_lowermodule}.${_version}"
+ QHP_VIRTUALFOLDER "qt${_lowermodule}"
+ IMPORTED TRUE
+ )
+ endif()
+ endforeach()
+ _ecm_setup_qt_qch_links(3D Gui Core)
+ _ecm_setup_qt_qch_links(Bluetooth DBus Core)
+ _ecm_setup_qt_qch_links(Concurrent Gui Core)
+ _ecm_setup_qt_qch_links(DBus Core)
+ _ecm_setup_qt_qch_links(Gui Core)
+ _ecm_setup_qt_qch_links(Location Positioning Gui Core)
+ _ecm_setup_qt_qch_links(Network Core)
+ _ecm_setup_qt_qch_links(Positioning Core)
+ _ecm_setup_qt_qch_links(PrintSupport Widgets Gui Core)
+ _ecm_setup_qt_qch_links(Qml Network Core)
+ _ecm_setup_qt_qch_links(Quick Qml Network Gui Core)
+ _ecm_setup_qt_qch_links(Sensors Core)
+ _ecm_setup_qt_qch_links(SerialPort Core)
+ _ecm_setup_qt_qch_links(Sql Core)
+ _ecm_setup_qt_qch_links(Svg Widgets Gui Core)
+ _ecm_setup_qt_qch_links(WebChannel Qml Core)
+ _ecm_setup_qt_qch_links(WebEngine Quick Qml Gui Core)
+ _ecm_setup_qt_qch_links(WebSockets Network Core)
+ _ecm_setup_qt_qch_links(Widgets Gui Core)
+ _ecm_setup_qt_qch_links(Xml Core)
+ _ecm_setup_qt_qch_links(XmlPatterns Network Core)
+ endif()
+ endif()
+endfunction()
+
+# Helper method: collect all qch targets from the LINK_QCHS dependency tree and set result to <var>
+function(_ecm_collect_linkable_qch_targets name)
+ set(_candidate_qchs ${ARGN})
+ set(_handled_qchs)
+ set(_good_qchs)
+ # while unhandled qch targets
+ while(_candidate_qchs)
+ # get another unhandled qch target
+ list(GET _candidate_qchs 0 _qch)
+ list(REMOVE_AT _candidate_qchs 0)
+ list(FIND _handled_qchs ${_qch} _index)
+ # if not already handled
+ if(_index EQUAL -1)
+ list(APPEND _handled_qchs ${_qch})
+ if(TARGET ${_qch})
+ # always look at other linked qch targets, also for incomplete targets
+ get_property(_link_qchs TARGET ${_qch} PROPERTY LINK_QCHS)
+ if(_link_qchs)
+ list(APPEND _candidate_qchs ${_link_qchs})
+ endif()
+ # check if this target has all needed properties
+ set(_target_usable TRUE)
+ foreach(_propertyname
+ DOXYGEN_TAGFILE
+ QHP_NAMESPACE
+ QHP_VIRTUALFOLDER
+ )
+ get_target_property(_property ${_qch} ${_propertyname})
+ if(NOT _property)
+ message(STATUS "No property ${_propertyname} set on ${_qch} when calling ecm_add_qch(). <<${_property}>>")
+ set(_target_usable FALSE)
+ endif()
+ endforeach()
+ get_target_property(_tagfile_build ${_qch} DOXYGEN_TAGFILE_BUILD)
+ if (NOT _tagfile_build)
+ get_target_property(_tagfile ${_qch} DOXYGEN_TAGFILE)
+ if(NOT EXISTS ${_tagfile})
+ message(STATUS "No such tag file \"${_tagfile}\" found for ${_qch} when calling ecm_add_qch().")
+ set(_target_usable FALSE)
+ endif()
+ endif()
+ if(_target_usable)
+ list(APPEND _good_qchs ${_qch})
+ else()
+ message(WARNING "No linking to API dox of ${_qch}.")
+ endif()
+ else()
+ message(STATUS "No such target ${_qch} defined when calling ecm_add_qch(), ignored.")
+ endif()
+ endif()
+ endwhile()
+ set(${name} ${_good_qchs} PARENT_SCOPE)
+endfunction()
+
+
+function(ecm_add_qch target_name)
+ # Parse arguments
+ set(options VERBOSE)
+ set(oneValueArgs NAME BASE_NAME QCH_INSTALL_DESTINATION TAGFILE_INSTALL_DESTINATION COMPONENT VERSION NAMESPACE MD_MAINPAGE ORG_DOMAIN CONFIG_TEMPLATE)
+ set(multiValueArgs SOURCE_DIRS SOURCES IMAGE_DIRS EXAMPLE_DIRS PREDEFINED_MACROS BLANK_MACROS LINK_QCHS)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ # check required args
+ foreach(_arg_name NAME QCH_INSTALL_DESTINATION TAGFILE_INSTALL_DESTINATION VERSION)
+ if(NOT DEFINED ARGS_${_arg_name})
+ message(FATAL_ERROR "${_arg_name} needs to be defined when calling ecm_add_qch")
+ endif()
+ endforeach()
+ if(NOT DEFINED ARGS_SOURCE_DIRS AND NOT DEFINED ARGS_SOURCES AND NOT DEFINED ARGS_CONFIG_TEMPLATE)
+ message(FATAL_ERROR "SOURCE_DIRS or SOURCES needs to be defined when calling ecm_add_qch")
+ endif()
+ if(DEFINED ARGS_SOURCE_DIRS AND DEFINED ARGS_SOURCES)
+ message(FATAL_ERROR "Either SOURCE_DIRS or SOURCES, not both, needs to be defined when calling ecm_add_qch")
+ endif()
+ if(NOT DEFINED ARGS_ORG_DOMAIN AND NOT DEFINED ARGS_NAMESPACE)
+ message(FATAL_ERROR "ORG_DOMAIN or NAMESPACE needs to be defined when calling ecm_add_qch")
+ endif()
+
+ # find required tools
+ # TODO: check with doxygen author if perl is really still required, PERL_PATH seems unused in doxygen
+ find_package(Perl)
+ set_package_properties(Perl PROPERTIES
+ PURPOSE "Needed for API dox QCH file generation"
+ TYPE OPTIONAL
+ )
+ if (NOT DOXYGEN_PATCHED_JSFILESADDED)
+ set(REQUIRED_DOXYGEN_VERSION 1.8.13)
+ endif()
+ find_package(Doxygen ${REQUIRED_DOXYGEN_VERSION})
+ if (NOT DOXYGEN_FOUND AND NOT DOXYGEN_PATCHED_JSFILESADDED)
+ 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)")
+ endif()
+ set_package_properties(Doxygen PROPERTIES
+ TYPE OPTIONAL
+ PURPOSE "Needed for API dox QCH file generation${doxygen_description_addition}"
+ )
+ find_package(QHelpGenerator)
+ set_package_properties(QHelpGenerator PROPERTIES
+ TYPE OPTIONAL
+ PURPOSE "Needed for API dox QCH file generation"
+ DESCRIPTION "Part of Qt5 tools"
+ )
+ set(_missing_tools)
+ if (NOT PERL_FOUND)
+ list(APPEND _missing_tools "Perl")
+ endif()
+ if (NOT DOXYGEN_FOUND)
+ list(APPEND _missing_tools "Doxygen")
+ endif()
+ if (NOT QHelpGenerator_FOUND)
+ list(APPEND _missing_tools "qhelpgenerator")
+ endif()
+
+ if (_missing_tools)
+ message(WARNING "API dox QCH file will not be generated, tools missing: ${_missing_tools}!")
+ else()
+ _ecm_ensure_qt_qch_targets()
+
+ # prepare base dirs, working file names and other vars
+ if (DEFINED ARGS_BASE_NAME)
+ set(_basename ${ARGS_BASE_NAME})
+ else()
+ set(_basename ${ARGS_NAME})
+ endif()
+ set(_qch_file_basename "${_basename}.qch")
+ set(_tags_file_basename "${_basename}.tags")
+ set(_qch_buildpath "${CMAKE_CURRENT_BINARY_DIR}/${_qch_file_basename}")
+ set(_tags_buildpath "${CMAKE_CURRENT_BINARY_DIR}/${_tags_file_basename}")
+ set(_apidox_builddir "${CMAKE_CURRENT_BINARY_DIR}/${_basename}_ECMQchDoxygen")
+ if (DEFINED ARGS_NAMESPACE)
+ set(_namespace "${ARGS_NAMESPACE}")
+ else()
+ set(_namespace "${ARGS_ORG_DOMAIN}.${ARGS_NAME}")
+ endif()
+ string(REPLACE "." "_" _dotLessVersion ${ARGS_VERSION})
+ set(_versioned_namespace "${_namespace}.${_dotLessVersion}")
+ set(_sources)
+ set(_dep_tagfiles)
+ set(_dep_qch_targets)
+
+ ### Create doxygen config file
+ set(_doxygenconfig_file "${CMAKE_CURRENT_BINARY_DIR}/${_basename}_ECMQchDoxygen.config")
+ if (DEFINED ARGS_CONFIG_TEMPLATE)
+ set(_doxygenconfig_template_file "${ARGS_CONFIG_TEMPLATE}")
+ else()
+ set(_doxygenconfig_template_file "${ECM_MODULE_DIR}/ECMQchDoxygen.config.in")
+ endif()
+ set(_doxygen_layout_file "${ECM_MODULE_DIR}/ECMQchDoxygenLayout.xml")
+ # Setup variables used in config file template, ECM_QCH_DOXYGEN_*
+ set(ECM_QCH_DOXYGEN_OUTPUTDIR "\"${_apidox_builddir}\"")
+ set(ECM_QCH_DOXYGEN_TAGFILE "\"${_tags_buildpath}\"")
+ set(ECM_QCH_DOXYGEN_LAYOUTFILE "\"${_doxygen_layout_file}\"")
+ set(ECM_QCH_DOXYGEN_IMAGEDIRS)
+ foreach(_image_DIR IN LISTS ARGS_IMAGE_DIRS)
+ if (NOT IS_ABSOLUTE ${_image_DIR})
+ set(_image_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_image_DIR}")
+ endif()
+ # concat dirs separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_IMAGEDIRS "${ECM_QCH_DOXYGEN_IMAGEDIRS} \\\n\"${_image_DIR}\"")
+ endforeach()
+ set(ECM_QCH_DOXYGEN_EXAMPLEDIRS)
+ foreach(_example_DIR IN LISTS ARGS_EXAMPLE_DIRS)
+ if (NOT IS_ABSOLUTE ${_example_DIR})
+ set(_example_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_example_DIR}")
+ endif()
+ # concat dirs separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_EXAMPLEDIRS "${ECM_QCH_DOXYGEN_EXAMPLEDIRS} \\\n\"${_example_DIR}\"")
+ endforeach()
+ if (ARGS_MD_MAINPAGE)
+ if (NOT IS_ABSOLUTE ${ARGS_MD_MAINPAGE})
+ set(ARGS_MD_MAINPAGE "${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_MD_MAINPAGE}")
+ endif()
+ set(ECM_QCH_DOXYGEN_MAINPAGE_MDFILE "\"${ARGS_MD_MAINPAGE}\"")
+ else()
+ set(ECM_QCH_DOXYGEN_MAINPAGE_MDFILE)
+ endif()
+ set(ECM_QCH_DOXYGEN_INPUT)
+ if (ARGS_SOURCE_DIRS)
+ foreach(_source_DIR IN LISTS ARGS_SOURCE_DIRS)
+ if (NOT IS_ABSOLUTE ${_source_DIR})
+ set(_source_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_source_DIR}")
+ endif()
+ # concat dirs separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_INPUT "${ECM_QCH_DOXYGEN_INPUT} \\\n\"${_source_DIR}\"")
+ endforeach()
+ if (ARGS_MD_MAINPAGE)
+ set(ECM_QCH_DOXYGEN_INPUT "${ECM_QCH_DOXYGEN_INPUT} \\\n\"${ARGS_MD_MAINPAGE}\"")
+ endif()
+ set(ECM_QCH_DOXYGEN_FILE_PATTERNS "*.h *.cpp *.hpp *.hh *.cc *.h++ *.c++ *.hxx *.cxx *.dox *.md")
+ else()
+ foreach(_source IN LISTS ARGS_SOURCES)
+ if (NOT IS_ABSOLUTE ${_source})
+ set(_source "${CMAKE_CURRENT_SOURCE_DIR}/${_source}")
+ endif()
+ list(APPEND _sources "${_source}")
+ endforeach()
+ if (ARGS_MD_MAINPAGE)
+ list(FIND _sources ${ARGS_MD_MAINPAGE} _mainpage_index)
+ if (_mainpage_index STREQUAL -1)
+ list(APPEND _sources "${ARGS_MD_MAINPAGE}")
+ endif()
+ endif()
+ foreach(_source IN LISTS _sources)
+ # concat sources separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_INPUT "${ECM_QCH_DOXYGEN_INPUT} \\\n\"${_source}\"")
+ endforeach()
+ set(ECM_QCH_DOXYGEN_FILE_PATTERNS "")
+ endif()
+
+ set(ECM_QCH_DOXYGEN_PROJECTNAME ${ARGS_NAME})
+ file(RELATIVE_PATH _builddirrelative_filepath "${_apidox_builddir}/html" ${_qch_buildpath})
+ set(ECM_QCH_DOXYGEN_FILEPATH "\"${_builddirrelative_filepath}\"")
+ set(ECM_QCH_DOXYGEN_PROJECTVERSION ${ARGS_VERSION})
+ string(TOLOWER ${ARGS_NAME} ECM_QCH_DOXYGEN_VIRTUALFOLDER)
+ set(ECM_QCH_DOXYGEN_FULLNAMESPACE ${_versioned_namespace})
+ set(ECM_QCH_DOXYGEN_PREDEFINED_MACROS)
+ foreach(_macro IN LISTS ARGS_PREDEFINED_MACROS)
+ # concat dirs separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_PREDEFINED_MACROS "${ECM_QCH_DOXYGEN_PREDEFINED_MACROS} \\\n${_macro}")
+ endforeach()
+ set(ECM_QCH_DOXYGEN_BLANK_MACROS)
+ foreach(_macro IN LISTS ARGS_BLANK_MACROS)
+ # concat dirs separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_BLANK_MACROS "${ECM_QCH_DOXYGEN_BLANK_MACROS} \\\n${_macro}=\"\"")
+ endforeach()
+
+ # create list of tag files for linking other QCH files
+ set(ECM_QCH_DOXYGEN_TAGFILES)
+ _ecm_collect_linkable_qch_targets(_link_qchs ${ARGS_LINK_QCHS})
+ foreach(_link_qch IN LISTS _link_qchs)
+ list(APPEND _dep_qch_targets ${_link_qch})
+ get_target_property(_link_qch_tagfile ${_link_qch} DOXYGEN_TAGFILE)
+ get_target_property(_link_qch_tagfile_build ${_link_qch} DOXYGEN_TAGFILE_BUILD)
+ get_target_property(_link_qch_namespace ${_link_qch} QHP_NAMESPACE)
+ get_target_property(_link_qch_virtualfolder ${_link_qch} QHP_VIRTUALFOLDER)
+ # if same build, then prefer build version over any installed one
+ if (_link_qch_tagfile_build)
+ set(_link_qch_tagfile ${_link_qch_tagfile_build})
+ list(APPEND _dep_tagfiles "${_link_qch_tagfile}")
+ endif()
+ get_property(_linkqchs TARGET ${_link_qch} PROPERTY LINK_QCHS)
+ set(_tagfile_entry "\"${_link_qch_tagfile}=qthelp://${_link_qch_namespace}/${_link_qch_virtualfolder}/\"")
+ # concat dirs separated by a break, it is no issue that first has also a leading break
+ set(ECM_QCH_DOXYGEN_TAGFILES "${ECM_QCH_DOXYGEN_TAGFILES} \\\n${_tagfile_entry}")
+ endforeach()
+
+ set(ECM_QCH_DOXYGEN_WARN_LOGFILE "\"${_doxygenconfig_file}.log\"")
+ if(ARGS_VERBOSE)
+ set(ECM_QCH_DOXYGEN_QUIET "NO")
+ else()
+ set(ECM_QCH_DOXYGEN_QUIET "YES")
+ endif()
+ set(ECM_QCH_DOXYGEN_PERL_EXECUTABLE "${PERL_EXECUTABLE}")
+ set(ECM_QCH_DOXYGEN_QHELPGENERATOR_EXECUTABLE ${QHelpGenerator_EXECUTABLE})
+
+ # finally create doxygen config file
+ configure_file(
+ "${_doxygenconfig_template_file}"
+ "${_doxygenconfig_file}"
+ @ONLY
+ )
+
+ # setup make target
+ set(_qch_INSTALLPATH ${ARGS_QCH_INSTALL_DESTINATION})
+ set(_tags_INSTALLPATH ${ARGS_TAGFILE_INSTALL_DESTINATION})
+ file(RELATIVE_PATH _relative_qch_file ${CMAKE_BINARY_DIR} ${_qch_buildpath})
+ file(RELATIVE_PATH _relative_tags_file ${CMAKE_BINARY_DIR} ${_tags_buildpath})
+ add_custom_command(
+ OUTPUT ${_qch_buildpath} ${_tags_buildpath}
+ COMMENT "Generating ${_relative_qch_file}, ${_relative_tags_file}"
+ COMMAND cmake -E remove_directory "${ECM_QCH_DOXYGEN_OUTPUTDIR}"
+ COMMAND cmake -E make_directory "${ECM_QCH_DOXYGEN_OUTPUTDIR}"
+ COMMAND ${DOXYGEN_EXECUTABLE} "${_doxygenconfig_file}"
+ DEPENDS
+ ${_doxygenconfig_file}
+ ${_doxygen_layout_file}
+ ${_sources}
+ ${_dep_tagfiles}
+ ${_dep_qch_targets}
+ )
+ add_custom_target(${target_name} ALL DEPENDS ${_qch_buildpath} ${_tags_buildpath})
+ set_target_properties(${target_name} PROPERTIES
+ DOXYGEN_TAGFILE "${_qch_INSTALLPATH}/${_tags_file_basename}"
+ DOXYGEN_TAGFILE_NAME "${_tags_file_basename}"
+ DOXYGEN_TAGFILE_INSTALLDIR "${_qch_INSTALLPATH}"
+ DOXYGEN_TAGFILE_BUILD "${_tags_buildpath}"
+ QHP_NAMESPACE "${_namespace}"
+ QHP_NAMESPACE_VERSIONED "${_versioned_namespace}"
+ QHP_VIRTUALFOLDER "${ECM_QCH_DOXYGEN_VIRTUALFOLDER}"
+ )
+ # list as value does not work with set_target_properties
+ set_property(TARGET ${target_name} PROPERTY LINK_QCHS "${ARGS_LINK_QCHS}")
+
+ if (DEFINED ARGS_COMPONENT)
+ set(_component COMPONENT ${ARGS_COMPONENT})
+ else()
+ set(_component)
+ endif()
+
+ # setup installation
+ install(FILES
+ ${_qch_buildpath}
+ DESTINATION ${_qch_INSTALLPATH}
+ ${_component}
+ )
+
+ install(FILES
+ ${_tags_buildpath}
+ DESTINATION ${_tags_INSTALLPATH}
+ ${_component}
+ )
+ endif()
+
+endfunction()
+
+
+function(ecm_install_qch_export)
+ set(options )
+ set(oneValueArgs FILE DESTINATION COMPONENT)
+ set(multiValueArgs TARGETS)
+
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(NOT DEFINED ARGS_FILE)
+ message(FATAL_ERROR "FILE needs to be defined when calling ecm_install_qch_export().")
+ endif()
+
+ if(NOT DEFINED ARGS_DESTINATION)
+ message(FATAL_ERROR "DESTINATION needs to be defined when calling ecm_install_qch_export().")
+ endif()
+
+ # TARGETS may be empty (and ARGS_TARGETS will not be defined then by cmake_parse_arguments)
+
+ set(_content
+"# This file was generated by ecm_install_qch_export(). DO NOT EDIT!
+"
+ )
+
+ foreach(_target IN LISTS ARGS_TARGETS)
+ set(_target_usable TRUE)
+
+ if (NOT TARGET ${_target})
+ message(STATUS "No such target ${_target} when calling ecm_install_qch_export().")
+ set(_target_usable FALSE)
+ else()
+ foreach(_propertyname
+ DOXYGEN_TAGFILE_NAME
+ DOXYGEN_TAGFILE_INSTALLDIR
+ QHP_NAMESPACE
+ QHP_NAMESPACE_VERSIONED
+ QHP_VIRTUALFOLDER
+ )
+ get_target_property(_property ${_target} ${_propertyname})
+ if(NOT _property)
+ message(STATUS "No property ${_propertyname} set on ${_target} when calling ecm_install_qch_export(). <${_property}>")
+ set(_target_usable FALSE)
+ endif()
+ endforeach()
+ endif()
+ if(_target_usable)
+ get_target_property(_tagfile_name ${_target} DOXYGEN_TAGFILE_NAME)
+ get_target_property(_tagfile_installdir ${_target} DOXYGEN_TAGFILE_INSTALLDIR)
+ if (NOT IS_ABSOLUTE ${_tagfile_installdir})
+ set(_tagfile_installdir "${CMAKE_INSTALL_PREFIX}/${_tagfile_installdir}")
+ endif()
+ get_target_property(_namespace ${_target} QHP_NAMESPACE)
+ get_target_property(_namespace_versioned ${_target} QHP_NAMESPACE_VERSIONED)
+ get_target_property(_virtualfolder ${_target} QHP_VIRTUALFOLDER)
+ get_property(_linkqchs TARGET ${_target} PROPERTY LINK_QCHS)
+ set(_content "${_content}
+if (NOT TARGET ${_target})
+
+add_custom_target(${_target})
+set_target_properties(${_target} PROPERTIES
+ DOXYGEN_TAGFILE \"${_tagfile_installdir}/${_tagfile_name}\"
+ QHP_NAMESPACE \"${_namespace}\"
+ QHP_NAMESPACE_VERSIONED \"${_namespace_versioned}\"
+ QHP_VIRTUALFOLDER \"${_virtualfolder}\"
+ IMPORTED TRUE
+)
+set_property(TARGET ${_target} PROPERTY LINK_QCHS ${_linkqchs})
+
+endif()
+"
+ )
+ else()
+ message(STATUS "No target exported for ${_target}.")
+ endif()
+ endforeach()
+
+ if (NOT IS_ABSOLUTE ${ARGS_FILE})
+ set(ARGS_FILE "${CMAKE_CURRENT_BINARY_DIR}/${ARGS_FILE}")
+ endif()
+
+ file(GENERATE
+ OUTPUT "${ARGS_FILE}"
+ CONTENT "${_content}"
+ )
+
+ if (DEFINED ARGS_COMPONENT)
+ set(_component COMPONENT ${ARGS_COMPONENT})
+ else()
+ set(_component)
+ endif()
+ install(
+ FILES "${ARGS_FILE}"
+ DESTINATION "${ARGS_DESTINATION}"
+ ${_component}
+ )
+
+endfunction()
diff --git a/modules/ECMQchDoxygen.config.in b/modules/ECMQchDoxygen.config.in
new file mode 100644
index 00000000..a00ad1a2
--- /dev/null
+++ b/modules/ECMQchDoxygen.config.in
@@ -0,0 +1,239 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = @ECM_QCH_DOXYGEN_PROJECTNAME@
+PROJECT_NUMBER = @ECM_QCH_DOXYGEN_PROJECTVERSION@
+OUTPUT_DIRECTORY = @ECM_QCH_DOXYGEN_OUTPUTDIR@
+GENERATE_TAGFILE = @ECM_QCH_DOXYGEN_TAGFILE@
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The \$name class" \
+ "The \$name widget" \
+ "The \$name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+# Do not require explicity @brief command for brief description
+JAVADOC_AUTOBRIEF = YES
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+BUILTIN_STL_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+LAYOUT_FILE = @ECM_QCH_DOXYGEN_LAYOUTFILE@
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+# Require classes to be documented to appear in apidox, but always document all
+# public and protected members (even if static)
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = YES
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+HIDE_COMPOUND_REFERENCE = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_MEMBERS_CTORS_1ST = YES
+SORT_BRIEF_DOCS = YES
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST = YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_FILES = YES
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = @ECM_QCH_DOXYGEN_QUIET@
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = YES
+WARN_FORMAT = "\$file:\$line: \$text"
+WARN_LOGFILE = @ECM_QCH_DOXYGEN_WARN_LOGFILE@
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = @ECM_QCH_DOXYGEN_INPUT@
+FILE_PATTERNS = @ECM_QCH_DOXYGEN_FILE_PATTERNS@
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS = */.svn/* \
+ */.git/* \
+ */cmake/* \
+ *.moc.* \
+ moc* \
+ *.all_cpp.* \
+ *unload.* \
+ */test/* \
+ */tests/* \
+ */autotests/* \
+ *_p.cpp \
+ *_p.h
+# Symbols from Qt that show up occassionlly and we don't want to see
+EXCLUDE_SYMBOLS = iterator const_iterator
+EXAMPLE_PATH = @ECM_QCH_DOXYGEN_EXAMPLEDIRS@
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH = @ECM_QCH_DOXYGEN_IMAGEDIRS@
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+USE_MDFILE_AS_MAINPAGE = @ECM_QCH_DOXYGEN_MAINPAGE_MDFILE@
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# do NOT generate any formats other than qhp
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+GENERATE_HTML = YES
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+GENERATE_RTF = NO
+GENERATE_XML = NO
+GENERATE_AUTOGEN_DEF = NO
+GENERATE_PERLMOD = NO
+DISABLE_INDEX = YES
+HTML_DYNAMIC_SECTIONS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the qhp output
+#---------------------------------------------------------------------------
+GENERATE_QHP = YES
+QCH_FILE = @ECM_QCH_DOXYGEN_FILEPATH@
+QHP_NAMESPACE = @ECM_QCH_DOXYGEN_FULLNAMESPACE@
+QHP_VIRTUAL_FOLDER = @ECM_QCH_DOXYGEN_VIRTUALFOLDER@
+QHG_LOCATION = @ECM_QCH_DOXYGEN_QHELPGENERATOR_EXECUTABLE@
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+TAGFILES = @ECM_QCH_DOXYGEN_TAGFILES@
+PERL_PATH = @ECM_QCH_DOXYGEN_PERL_EXECUTABLE@
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = NO
+COLLABORATION_GRAPH = NO
+GROUP_GRAPHS = NO
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = NO
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = NO
+DIRECTORY_GRAPH = NO
+GENERATE_LEGEND = NO
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+
+
+### KDE Settings
+ALIASES = "intern=\par<b>Internal use only.</b>" \
+ "reimp=\par<b>Reimplemented from superclass.</b>" \
+ "obsolete=@deprecated" \
+ "feature=\xrefitem features \"Feature(s)\" \"Features\"" \
+ "unmaintained=\xrefitem unmaintained \"Unmaintained\" \"Unmaintained\"" \
+ "requirement=\xrefitem requirements \"Requirement(s)\" \"Requirements\"" \
+ "faq=\xrefitem FAQ \"F.A.Q.\" \"F.A.Q.\"" \
+ "authors=\xrefitem authors \"Author(s)\" \"Authors\"" \
+ "maintainers=\xrefitem maintainers \"Maintainer(s)\" \"Maintainers\"" \
+ "glossary=\xrefitem glossary \"Glossary\" \"Glossary\"" \
+ "acronym=\b " \
+ "licenses=\xrefitem licenses \"License(s)\" \"Licenses\"" \
+ "FIXME=\xrefitem fixme \"Fixme\" \"Fixme\"" \
+ "bc=\xrefitem bc \"Binary Compatible\" \"Binary Compatible\"" \
+ "threadsafe=\xrefitem threadsafe \"Threadsafe\" \"Threadsafe\"" \
+ "artistic=<a href=\"http://www.opensource.org/licenses/artistic-license.php\">Artistic</a>" \
+ "bsd=<a href=\"http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5\">BSD</a>" \
+ "x11=<a href=\"http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3\">X11</a>" \
+ "gpl=<a href=\"http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC1\">GPLv2</a>" \
+ "lgpl=<a href=\"http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html#SEC1\">LGPLv2</a>" \
+ "mit=<a href=\"http://www.opensource.org/licenses/mit-license.php\">MIT</a>" \
+ "qpl=<a href=\"http://doc.trolltech.com/3.0/license.html\">QPL</a>"
+
+PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \
+\
+ Q_WS_X11="" \
+ Q_WS_WIN="" \
+ Q_WS_MAC="" \
+ Q_WS_QWS="" \
+ Q_WS_MAEMO_5="" \
+ Q_OS_LINUX="" \
+ Q_OS_UNIX="" \
+ Q_OS_WIN="" \
+ Q_OS_MAC="" \
+ Q_OS_MACX="" \
+ Q_OS_DARWIN="" \
+ Q_OS_FREEBSD="" \
+ Q_OS_NETBSD="" \
+ Q_OS_OPENBSD="" \
+ Q_OS_BSD4="" \
+ Q_OS_SOLARIS="" \
+ Q_OS_IRIX="" \
+\
+ Q_SLOTS="slots" \
+ Q_SIGNALS="signals" \
+ Q_DECL_CONSTEXPR="constexpr" \
+ Q_DECL_FINAL="final" \
+ Q_DECL_NULLPTR="nullptr" \
+ Q_DECL_OVERRIDE="override" \
+ Q_DECL_HIDDEN="" \
+ Q_REQUIRED_RESULT="" \
+ Q_SCRIPTABLE="" \
+ Q_INVOKABLE="" \
+ @ECM_QCH_DOXYGEN_PREDEFINED_MACROS@ \
+ @ECM_QCH_DOXYGEN_BLANK_MACROS@
diff --git a/modules/ECMQchDoxygenLayout.xml b/modules/ECMQchDoxygenLayout.xml
new file mode 100644
index 00000000..f3638dd5
--- /dev/null
+++ b/modules/ECMQchDoxygenLayout.xml
@@ -0,0 +1,194 @@
+<doxygenlayout version="1.0">
+ <!-- Generated by doxygen 1.8.7 -->
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespacelist" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="">
+ <tab type="classlist" visible="yes" title="" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="filelist" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <properties title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <properties title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <events title=""/>
+ </memberdef>
+ <allmemberslink visible="yes"/>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="no"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="no"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="yes"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 3ce089d0..7ebcf9b5 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -158,6 +158,7 @@ if (TARGET Qt5::qmake)
--build-options -DKDE_INSTALL_USE_QT_SYS_PATHS=TRUE
-DPLUGINDIR_should_be_absolute=TRUE
-DQMLDIR_should_be_absolute=TRUE
+ -DQTQCHDIR_should_be_absolute=TRUE
-DQTPLUGINDIR_should_be_absolute=TRUE
-DQTQUICKIMPORTSDIR_should_be_absolute=TRUE
)
diff --git a/tests/KDEInstallDirsTest/var_list.cmake b/tests/KDEInstallDirsTest/var_list.cmake
index 39bd90fa..f6dc95d1 100644
--- a/tests/KDEInstallDirsTest/var_list.cmake
+++ b/tests/KDEInstallDirsTest/var_list.cmake
@@ -33,8 +33,10 @@ set(var_suffixes
MIMEDIR
METAINFODIR
PLUGINDIR
+ QCHDIR
QMLDIR
QTPLUGINDIR
+ QTQCHDIR
QTQUICKIMPORTSDIR
SBINDIR
SHAREDSTATEDIR