diff options
author | l10n daemon script <scripty@kde.org> | 2015-11-08 21:01:33 +0000 |
---|---|---|
committer | l10n daemon script <scripty@kde.org> | 2015-11-08 21:01:33 +0000 |
commit | 7feccae76e01a65b406995b5ba9526fe9ade4299 (patch) | |
tree | 99011137f4dedcf4bf242e167ac7dc70d9136b8e | |
parent | a1bb0b0488843165e606771b75a3a67ba8a131a6 (diff) | |
parent | c88bc78e0ca3834c46b89ca9d14b404751da5d4a (diff) | |
download | extra-cmake-modules-5.16.0.tar.gz extra-cmake-modules-5.16.0.tar.bz2 |
Merge remote-tracking branch 'origin/master' into local_releasev5.16.0-rc2v5.16.0
109 files changed, 2368 insertions, 284 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c8e5f56..c1abd6c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) project(extra-cmake-modules NONE) -set(ECM_MAJOR_VERSION 1) -set(ECM_MINOR_VERSION 6) +set(ECM_MAJOR_VERSION 5) +set(ECM_MINOR_VERSION 16) set(ECM_PATCH_VERSION 0) set(ECM_VERSION ${ECM_MAJOR_VERSION}.${ECM_MINOR_VERSION}.${ECM_PATCH_VERSION}) @@ -14,7 +14,8 @@ if(BUILD_TESTING) add_subdirectory(tests) endif() -set(SHARE_INSTALL_DIR share) +set(SHARE_INSTALL_DIR share CACHE PATH "read-only architecture-independent data") +set(TOOLCHAIN_MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/toolchain/) set(MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/modules/) set(KDE_MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/kde-modules/) set(FIND_MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/find-modules/) @@ -33,6 +34,9 @@ install(FILES ${installKdeModuleFiles} DESTINATION ${KDE_MODULES_INSTALL_DIR}) file(GLOB installFindModuleFiles ${CMAKE_SOURCE_DIR}/find-modules/*[^~]) install(FILES ${installFindModuleFiles} DESTINATION ${FIND_MODULES_INSTALL_DIR}) +file(GLOB installToolchainModuleFiles ${CMAKE_SOURCE_DIR}/toolchain/*[^~]) +install(FILES ${installToolchainModuleFiles} DESTINATION ${TOOLCHAIN_MODULES_INSTALL_DIR}) + include(CMakePackageConfigHelpers) @@ -5,8 +5,9 @@ Introduction ============ The Extra CMake Modules package, or ECM, adds to the modules provided by CMake, -including both ones used by ``find_package()`` to find common software and ones -that can be used directly in ``CMakeLists.txt`` files to perform common tasks. +including ones used by ``find_package()`` to find common software, ones that +can be used directly in ``CMakeLists.txt`` files to perform common tasks and +toolchain files that must be specified on the commandline by the user. In addition, it provides common build settings used in software produced by the KDE community. @@ -54,7 +55,7 @@ some of the settings. Some of the functionality of Organization ------------ -ECM provides three different types of modules. +ECM provides four different types of modules. * Core modules provide helpful macros for use in project CMake scripts. See :manual:`ecm-modules(7)` for more information. @@ -63,6 +64,8 @@ ECM provides three different types of modules. * KDE modules provide common settings for software produced by KDE; much of this may also be useful to other projects. See :manual:`ecm-kde-modules(7)` for more information. +* Toolchain files change the build tools and targets used by CMake. See + :manual:`ecm-toolchains(7)` for more information. The ``${ECM_MODULE_DIR}``, ``${ECM_FIND_MODULE_DIR}`` and ``${ECM_KDE_MODULE_DIR}`` variables may be used instead of diff --git a/docs/find-module/FindPng2Ico.rst b/docs/find-module/FindPng2Ico.rst new file mode 100644 index 00000000..db8aa775 --- /dev/null +++ b/docs/find-module/FindPng2Ico.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../find-modules/FindPng2Ico.cmake diff --git a/docs/manual/ecm-modules.7.rst b/docs/manual/ecm-modules.7.rst index 16fd8612..ee0e4638 100644 --- a/docs/manual/ecm-modules.7.rst +++ b/docs/manual/ecm-modules.7.rst @@ -11,12 +11,12 @@ Introduction ============ Extra CMake Modules (ECM) provides various modules that provide useful functions -for CMake scripts. ECM actually provides three types of modules: those that -extend the functionality of the ``find_package`` command are documented in -:manual:`ecm-find-modules(7)`; those that provide standard settings for software -produced by the KDE community are documented in :manual:`ecm-kde-modules(7)`. -The rest provide macros and functions for general use by CMake scripts and are -documented here. +for CMake scripts. ECM actually provides three types of modules that can be +used from CMake scripts: those that extend the functionality of the +``find_package`` command are documented in :manual:`ecm-find-modules(7)`; those +that provide standard settings for software produced by the KDE community are +documented in :manual:`ecm-kde-modules(7)`. The rest provide macros and +functions for general use by CMake scripts and are documented here. To use these modules, you need to tell CMake to find the ECM package, and then add either ``${ECM_MODULE_PATH}`` or ``${ECM_MODULE_DIR}`` to the @@ -30,6 +30,10 @@ then add either ``${ECM_MODULE_PATH}`` or ``${ECM_MODULE_DIR}`` to the Using ``${ECM_MODULE_PATH}`` will also make the find modules and KDE modules available. +Note that there are also toolchain modules, documented in +:manual:`ecm-toolchains(7)`, but these are used by users building the software +rather than developers writing CMake scripts. + All Modules =========== diff --git a/docs/manual/ecm-toolchains.7.rst b/docs/manual/ecm-toolchains.7.rst new file mode 100644 index 00000000..66f685e2 --- /dev/null +++ b/docs/manual/ecm-toolchains.7.rst @@ -0,0 +1,33 @@ +.. ecm-manual-description: ECM Toolchains Reference + +ecm-toolchains(7) +***************** + +.. only:: html or latex + + .. contents:: + +Introduction +============ + +Extra CMake Modules (ECM) provides some toolchain modules. Unlike normal +modules, these are not included directly in projects, but specified with +the ``CMAKE_TOOLCHAIN_FILE`` cache variable on the commandline. + + +All Modules +=========== + +.. toctree:: + :maxdepth: 1 + :glob: + + /toolchain/* + +.. only:: man + + See Also + ======== + + :manual:`ecm(7)` + diff --git a/docs/module/ECMAddAppIcon.rst b/docs/module/ECMAddAppIcon.rst new file mode 100644 index 00000000..31c09a88 --- /dev/null +++ b/docs/module/ECMAddAppIcon.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMAddAppIcon.cmake diff --git a/docs/module/ECMCoverageOption.rst b/docs/module/ECMCoverageOption.rst new file mode 100644 index 00000000..41bffd78 --- /dev/null +++ b/docs/module/ECMCoverageOption.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMCoverageOption.cmake diff --git a/docs/module/ECMEnableSanitizers.rst b/docs/module/ECMEnableSanitizers.rst new file mode 100644 index 00000000..e25dd4f8 --- /dev/null +++ b/docs/module/ECMEnableSanitizers.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMEnableSanitizers.cmake diff --git a/docs/module/ECMGeneratePkgConfigFile.rst b/docs/module/ECMGeneratePkgConfigFile.rst new file mode 100644 index 00000000..cd311f6b --- /dev/null +++ b/docs/module/ECMGeneratePkgConfigFile.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMGeneratePkgConfigFile.cmake diff --git a/docs/module/ECMQtDeclareLoggingCategory.rst b/docs/module/ECMQtDeclareLoggingCategory.rst new file mode 100644 index 00000000..8f0af2ac --- /dev/null +++ b/docs/module/ECMQtDeclareLoggingCategory.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMQtDeclareLoggingCategory.cmake diff --git a/docs/module/ECMUninstallTarget.rst b/docs/module/ECMUninstallTarget.rst new file mode 100644 index 00000000..a1895158 --- /dev/null +++ b/docs/module/ECMUninstallTarget.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMUninstallTarget.cmake diff --git a/docs/sphinx/ecm.py b/docs/sphinx/ecm.py index 3eb75248..ed966bfb 100644 --- a/docs/sphinx/ecm.py +++ b/docs/sphinx/ecm.py @@ -154,6 +154,7 @@ _ecm_index_objs = { 'module': _ecm_index_entry('module'), 'find-module': _ecm_index_entry('find-module'), 'kde-module': _ecm_index_entry('kde-module'), + 'toolchain': _ecm_index_entry('toolchain'), } def _ecm_object_inventory(env, document, line, objtype, targetid): @@ -264,6 +265,7 @@ class ECMDomain(Domain): 'kde-module': ObjType('kde-module', 'kde-module'), 'find-module': ObjType('find-module', 'find-module'), 'manual': ObjType('manual', 'manual'), + 'toolchain': ObjType('toolchain', 'toolchain'), } directives = {} roles = { @@ -271,6 +273,7 @@ class ECMDomain(Domain): 'kde-module': XRefRole(), 'find-module': XRefRole(), 'manual': XRefRole(), + 'toolchain': XRefRole(), } initial_data = { 'objects': {}, # fullname -> docname, objtype diff --git a/docs/toolchain/Android.rst b/docs/toolchain/Android.rst new file mode 100644 index 00000000..9103e622 --- /dev/null +++ b/docs/toolchain/Android.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../toolchain/Android.cmake diff --git a/find-modules/FindEGL.cmake b/find-modules/FindEGL.cmake index 99d268df..b8787d8b 100644 --- a/find-modules/FindEGL.cmake +++ b/find-modules/FindEGL.cmake @@ -29,6 +29,8 @@ # In general we recommend using the imported target, as it is easier to use. # Bear in mind, however, that if the target is in the link interface of an # exported library, it must be made available by the package config file. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -58,12 +60,9 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "CMake 2.8.12 is required by FindEGL.cmake") -endif() -if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) - message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindEGL.cmake") -endif() +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(EGL) # Use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls @@ -96,14 +95,14 @@ if(EGL_INCLUDE_DIR) # finding all these defines and selecting the highest numbered. file(READ "${EGL_INCLUDE_DIR}/egl.h" _EGL_header_contents) string(REGEX MATCHALL - "[ \\t]EGL_VERSION_[0-9_]+" + "[ \t]EGL_VERSION_[0-9_]+" _EGL_version_lines "${_EGL_header_contents}" ) unset(_EGL_header_contents) foreach(_EGL_version_line ${_EGL_version_lines}) string(REGEX REPLACE - "[ \\t]EGL_VERSION_([0-9_]+)" + "[ \t]EGL_VERSION_([0-9_]+)" "\\1" _version_candidate "${_EGL_version_line}" diff --git a/find-modules/FindKF5.cmake b/find-modules/FindKF5.cmake index 2e1fca87..b0ba9f6b 100644 --- a/find-modules/FindKF5.cmake +++ b/find-modules/FindKF5.cmake @@ -16,6 +16,8 @@ # If all the required components (those given in the COMPONENTS argument, but # not those given in the OPTIONAL_COMPONENTS argument) are found, ``KF5_FOUND`` # will be set to true. Otherwise, it will be set to false. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -45,12 +47,9 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "CMake 2.8.12 is required by FindKF5.cmake") -endif() -if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) - message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindKF5.cmake") -endif() +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(KF5) if (NOT KF5_FIND_COMPONENTS) set(KF5_NOT_FOUND_MESSAGE "The KF5 package requires at least one component") diff --git a/find-modules/FindLibGit2.cmake b/find-modules/FindLibGit2.cmake index 3bb87c29..eaf227fc 100644 --- a/find-modules/FindLibGit2.cmake +++ b/find-modules/FindLibGit2.cmake @@ -1,6 +1,6 @@ #.rst: # FindLibGit2 -# ------- +# ----------- # # Try to find libgit2 on a Unix system. # @@ -28,6 +28,8 @@ # In general we recommend using the imported target, as it is easier to use. # Bear in mind, however, that if the target is in the link interface of an # exported library, it must be made available by the package config file. +# +# Since 1.3.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -58,12 +60,9 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "CMake 2.8.12 is required by FindLibGit2.cmake") -endif() -if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) - message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindLibGit2.cmake") -endif() +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(LibGit2) # Use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls diff --git a/find-modules/FindOpenEXR.cmake b/find-modules/FindOpenEXR.cmake index 85afebdf..d80caadd 100644 --- a/find-modules/FindOpenEXR.cmake +++ b/find-modules/FindOpenEXR.cmake @@ -23,6 +23,8 @@ # In general we recommend using the imported target, as it is easier to use. # Bear in mind, however, that if the target is in the link interface of an # exported library, it must be made available by the package config file. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2013-2014 Alex Merry <alex.merry@kdemail.net> @@ -52,10 +54,9 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) -if(${CMAKE_VERSION} VERSION_LESS 2.8.12) - message(FATAL_ERROR "CMake 2.8.12 is required by FindOpenEXR.cmake") -endif() +ecm_find_package_version_check(OpenEXR) # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls diff --git a/find-modules/FindPng2Ico.cmake b/find-modules/FindPng2Ico.cmake new file mode 100644 index 00000000..d84f6673 --- /dev/null +++ b/find-modules/FindPng2Ico.cmake @@ -0,0 +1,117 @@ +#.rst: +# FindPng2Ico +# ----------- +# +# Try to find png2ico. +# +# If the png2ico executable is not in your PATH, you can provide +# an alternative name or full path location with the ``Png2Ico_EXECUTABLE`` +# variable. +# +# This will define the following variables: +# +# ``Png2Ico_FOUND`` +# True if png2ico is available. +# +# ``Png2Ico_EXECUTABLE`` +# The png2ico executable. +# +# If ``Png2Ico_FOUND`` is TRUE, it will also define the following imported +# target: +# +# ``Png2Ico::Png2Ico`` +# The png2ico executable. +# +# and the following variables: +# +# ``Png2Ico_HAS_COLORS_ARGUMENT`` +# Whether png2ico accepts a ``--colors`` argument. `Matthias Benkmann's +# tool <http://www.winterdrache.de/freeware/png2ico/>`_ does, while the +# version of png2ico from the `"KDE On Windows" (kdewin) +# <https://projects.kde.org/projects/kdesupport/kdewin>`_ project does not. +# +# ``Png2Ico_HAS_RCFILE_ARGUMENT`` +# Whether png2ico accepts an ``--rcfile`` argument. The version of png2ico +# from the `"KDE On Windows" (kdewin) +# <https://projects.kde.org/projects/kdesupport/kdewin>`_ project does, +# while `Matthias Benkmann's tool +# <http://www.winterdrache.de/freeware/png2ico/>`_ does not. +# +# Since 1.7.0. + +#============================================================================= +# Copyright 2014 Alex Merry <alex.merry@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(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(Png2Ico) + +# Find png2ico +find_program(Png2Ico_EXECUTABLE NAMES png2ico) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Png2Ico + FOUND_VAR + Png2Ico_FOUND + REQUIRED_VARS + Png2Ico_EXECUTABLE +) + +mark_as_advanced(Png2Ico_EXECUTABLE) + +if (Png2Ico_FOUND) + execute_process( + COMMAND "${Png2Ico_EXECUTABLE}" --help + OUTPUT_VARIABLE _png2ico_help_text + ERROR_VARIABLE _png2ico_help_text + ) + if (_png2ico_help_text MATCHES ".*--rcfile .*") + set(Png2Ico_HAS_RCFILE_ARGUMENT TRUE) + else() + set(Png2Ico_HAS_RCFILE_ARGUMENT FALSE) + endif() + if (_png2ico_help_text MATCHES ".*--colors .*") + set(Png2Ico_HAS_COLORS_ARGUMENT TRUE) + else() + set(Png2Ico_HAS_COLORS_ARGUMENT FALSE) + endif() + unset(_png2ico_help_text) + + if (NOT TARGET Png2Ico::Png2Ico) + add_executable(Png2Ico::Png2Ico IMPORTED) + set_target_properties(Png2Ico::Png2Ico PROPERTIES + IMPORTED_LOCATION "${Png2Ico_EXECUTABLE}" + ) + endif() +endif() + +include(FeatureSummary) +set_package_properties(Png2Ico PROPERTIES + URL "http://www.winterdrache.de/freeware/png2ico/ or https://projects.kde.org/projects/kdesupport/kdewin" + DESCRIPTION "Executable that converts a collection of PNG files into a Windows icon file" +) + diff --git a/find-modules/FindQtWaylandScanner.cmake b/find-modules/FindQtWaylandScanner.cmake index 7fb8a009..79a1b051 100644 --- a/find-modules/FindQtWaylandScanner.cmake +++ b/find-modules/FindQtWaylandScanner.cmake @@ -55,6 +55,8 @@ # names don't start with ``qt_`` or ``wl_``. # # WaylandScanner is required and will be searched for. +# +# Since 1.4.0. #============================================================================= # Copyright 2012-2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> @@ -88,7 +90,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) ecm_find_package_version_check(QtWaylandScanner) # Find qtwaylandscanner -find_program(QtWaylandScanner_EXECUTABLE NAMES qtwaylandscanner) +find_program(QtWaylandScanner_EXECUTABLE NAMES qtwaylandscanner HINTS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/qt5/bin/) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(QtWaylandScanner diff --git a/find-modules/FindSharedMimeInfo.cmake b/find-modules/FindSharedMimeInfo.cmake index 263a5028..00bebf16 100644 --- a/find-modules/FindSharedMimeInfo.cmake +++ b/find-modules/FindSharedMimeInfo.cmake @@ -23,6 +23,8 @@ # Updates the XDG mime database at install time (unless the ``$DESTDIR`` # environment variable is set, in which case it is up to package managers to # perform this task). +# +# Since pre-1.0.0. #============================================================================= # Copyright 2013-2014 Alex Merry <alex.merry@kdemail.net> @@ -52,12 +54,9 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "CMake 2.8.12 is required by FindSharedMimeInfo.cmake") -endif() -if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) - message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindSharedMimeInfo.cmake") -endif() +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(SharedMimeInfo) find_program (UPDATE_MIME_DATABASE_EXECUTABLE NAMES update-mime-database) diff --git a/find-modules/FindWayland.cmake b/find-modules/FindWayland.cmake index 490ab1be..c5a56c16 100644 --- a/find-modules/FindWayland.cmake +++ b/find-modules/FindWayland.cmake @@ -44,6 +44,8 @@ # and provide more control. Bear in mind, however, that if any target is in the # link interface of an exported library, it must be made available by the # package config file. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -115,7 +117,7 @@ if(NOT Wayland_VERSION) if(Wayland_VERSION_HEADER) file(READ ${Wayland_VERSION_HEADER} _wayland_version_header_contents) string(REGEX REPLACE - "^.*[ \\t]+WAYLAND_VERSION[ \\t]+\"([0-9.]*)\".*$" + "^.*[ \t]+WAYLAND_VERSION[ \t]+\"([0-9.]*)\".*$" "\\1" Wayland_VERSION "${_wayland_version_header_contents}" diff --git a/find-modules/FindWaylandScanner.cmake b/find-modules/FindWaylandScanner.cmake index 33c46f9b..4052cdab 100644 --- a/find-modules/FindWaylandScanner.cmake +++ b/find-modules/FindWaylandScanner.cmake @@ -47,6 +47,8 @@ # Generate Wayland server protocol files from ``<xmlfile>`` XML # definition for the ``<basename>`` interface and append those files # to ``<source_files_var>``. +# +# Since 1.4.0. #============================================================================= # Copyright 2012-2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> diff --git a/find-modules/FindX11_XCB.cmake b/find-modules/FindX11_XCB.cmake index eafa08e2..dd55fd7b 100644 --- a/find-modules/FindX11_XCB.cmake +++ b/find-modules/FindX11_XCB.cmake @@ -30,6 +30,8 @@ # In general we recommend using the imported target, as it is easier to use. # Bear in mind, however, that if the target is in the link interface of an # exported library, it must be made available by the package config file. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -61,12 +63,9 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -if(CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "CMake 2.8.12 is required by FindX11_XCB.cmake") -endif() -if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) - message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindX11_XCB.cmake") -endif() +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(X11_XCB) # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls diff --git a/find-modules/FindXCB.cmake b/find-modules/FindXCB.cmake index 781b15c5..b2a800f7 100644 --- a/find-modules/FindXCB.cmake +++ b/find-modules/FindXCB.cmake @@ -51,6 +51,8 @@ # and provide more control. Bear in mind, however, that if any target is in the # link interface of an exported library, it must be made available by the # package config file. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2011 Fredrik Höglund <fredrik@kde.org> diff --git a/kde-modules/KDECMakeSettings.cmake b/kde-modules/KDECMakeSettings.cmake index 4ccbf82e..8e7ff359 100644 --- a/kde-modules/KDECMakeSettings.cmake +++ b/kde-modules/KDECMakeSettings.cmake @@ -41,6 +41,23 @@ # # This section can be disabled by setting ``KDE_SKIP_BUILD_SETTINGS`` to TRUE # before including this module. +# +# This section also provides an "uninstall" target that can be individually +# disabled by setting ``KDE_SKIP_UNINSTALL_TARGET`` to TRUE before including +# this module. +# +# By default on OS X, X11 and XCB related detections are disabled. However if +# the need would arise to use these technologies, the detection can be enabled +# by setting ``APPLE_FORCE_X11`` to ``ON``. +# +# A warning is printed for the developer to know that the detection is disabled on OS X. +# This message can be turned off by setting ``APPLE_SUPPRESS_X11_WARNING`` to ``ON``. +# +# Since pre-1.0.0. +# +# - Uninstall target functionality since 1.7.0. +# - ``APPLE_FORCE_X11`` option since 5.14.0 (detecting X11 was previously the default behavior) +# - ``APPLE_SUPPRESS_X11_WARNING`` option since 5.14.0 #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -78,21 +95,23 @@ if(NOT KDE_SKIP_RPATH_SETTINGS) endif() if (UNIX) + # for mac os: add install name dir in addition + # check: is the rpath stuff below really required on mac os? at least it seems so to use a stock qt from qt.io if (APPLE) set(CMAKE_INSTALL_NAME_DIR ${_abs_LIB_INSTALL_DIR}) - else () - # add our LIB_INSTALL_DIR to the RPATH (but only when it is not one of - # the standard system link directories - such as /usr/lib on UNIX) - list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${_abs_LIB_INSTALL_DIR}" _isSystemLibDir) - list(FIND CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "${_abs_LIB_INSTALL_DIR}" _isSystemCxxLibDir) - list(FIND CMAKE_C_IMPLICIT_LINK_DIRECTORIES "${_abs_LIB_INSTALL_DIR}" _isSystemCLibDir) - if("${_isSystemLibDir}" STREQUAL "-1" AND "${_isSystemCxxLibDir}" STREQUAL "-1" AND "${_isSystemCLibDir}" STREQUAL "-1") - set(CMAKE_INSTALL_RPATH "${_abs_LIB_INSTALL_DIR}") - endif() - - # Append directories in the linker search path (but outside the project) - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) endif () + + # add our LIB_INSTALL_DIR to the RPATH (but only when it is not one of + # the standard system link directories - such as /usr/lib on UNIX) + list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${_abs_LIB_INSTALL_DIR}" _isSystemLibDir) + list(FIND CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "${_abs_LIB_INSTALL_DIR}" _isSystemCxxLibDir) + list(FIND CMAKE_C_IMPLICIT_LINK_DIRECTORIES "${_abs_LIB_INSTALL_DIR}" _isSystemCLibDir) + if("${_isSystemLibDir}" STREQUAL "-1" AND "${_isSystemCxxLibDir}" STREQUAL "-1" AND "${_isSystemCLibDir}" STREQUAL "-1") + set(CMAKE_INSTALL_RPATH "${_abs_LIB_INSTALL_DIR}") + endif() + + # Append directories in the linker search path (but outside the project) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) endif (UNIX) endif() @@ -177,5 +196,25 @@ if(NOT KDE_SKIP_BUILD_SETTINGS) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") endif() + # Disable detection of X11 and related package on OS X because when using + # brew or macports, X11 can be installed and thus is detected. + option(APPLE_FORCE_X11 "Force enable X11 related detection on OS X" OFF) + option(APPLE_SUPPRESS_X11_WARNING "Suppress X11 and related technologies search disabling warning on OS X" OFF) + + if(APPLE AND NOT APPLE_FORCE_X11) + if (NOT APPLE_SUPPRESS_X11_WARNING) + message(WARNING "Searching for X11 and related technologies is disabled on Apple systems. Set APPLE_FORCE_X11 to ON to change this behaviour. Set APPLE_SUPPRESS_X11_WARNING to ON to hide this warning.") + endif() + + set(CMAKE_DISABLE_FIND_PACKAGE_X11 true) + set(CMAKE_DISABLE_FIND_PACKAGE_XCB true) + set(CMAKE_DISABLE_FIND_PACKAGE_Qt5X11Extras true) + endif() + + option(KDE_SKIP_UNINSTALL_TARGET "Prevent an \"uninstall\" target from being generated." OFF) + if(NOT KDE_SKIP_UNINSTALL_TARGET) + include("${ECM_MODULE_DIR}/ECMUninstallTarget.cmake") + endif() + endif() ################################################################### diff --git a/kde-modules/KDECompilerSettings.cmake b/kde-modules/KDECompilerSettings.cmake index aa0249d9..73d77825 100644 --- a/kde-modules/KDECompilerSettings.cmake +++ b/kde-modules/KDECompilerSettings.cmake @@ -29,6 +29,8 @@ # # Enables exceptions for C++ source files compiled for the # CMakeLists.txt file in the current directory and all subdirectories. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -194,6 +196,7 @@ if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR endif() # Default to hidden visibility for symbols +set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) diff --git a/kde-modules/KDEFrameworkCompilerSettings.cmake b/kde-modules/KDEFrameworkCompilerSettings.cmake index 3b77fc3c..e88c10d9 100644 --- a/kde-modules/KDEFrameworkCompilerSettings.cmake +++ b/kde-modules/KDEFrameworkCompilerSettings.cmake @@ -11,6 +11,8 @@ # For example, constructions like QString("foo") are prohibited, instead # forcing the use of QLatin1String or QStringLiteral, and some # Qt-defined keywords like signals and slots will not be defined. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2013 Albert Astals Cid <aacid@kde.org> @@ -38,11 +40,16 @@ add_definitions(-DQT_NO_CAST_TO_ASCII -DQT_USE_FAST_OPERATOR_PLUS -DQT_USE_QSTRINGBUILDER ) -if(NOT MSVC) - # QT_STRICT_ITERATORS breaks MSVC: it tries to link to QTypedArrayData symbols - # when using foreach. However these symbols don't actually exist. - # Not having QT_STRICT_ITERATORS defined fixes this issue. - # This is fixed by https://codereview.qt-project.org/#change,76311 - # TODO: set QT_STRICT_ITERATORS on all platforms once we depend on Qt 5.3 - add_definitions(-DQT_STRICT_ITERATORS) + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-DQT_STRICT_ITERATORS) +endif() + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # -Wgnu-zero-variadic-macro-arguments is triggered by every qCDebug() call and therefore results + # in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour + # instead of the exact standard wording so we can safely ignore it + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wno-gnu-zero-variadic-macro-arguments") endif() diff --git a/kde-modules/KDEInstallDirs.cmake b/kde-modules/KDEInstallDirs.cmake index 72a67641..b7cd34d8 100644 --- a/kde-modules/KDEInstallDirs.cmake +++ b/kde-modules/KDEInstallDirs.cmake @@ -132,7 +132,8 @@ # ``KDE_INSTALL_DIRS_NO_DEPRECATED`` is set to TRUE, only those variables # defined by the ``GNUInstallDirs`` module (shipped with CMake) are defined. # If ``KDE_INSTALL_DIRS_NO_CMAKE_VARIABLES`` is set to TRUE, no variables with -# a ``CMAKE_`` prefix will be defined by this module. +# a ``CMAKE_`` prefix will be defined by this module (other than +# CMAKE_INSTALL_DEFAULT_COMPONENT_NAME - see below). # # The ``KDE_INSTALL_<dir>`` variables (or their ``CMAKE_INSTALL_<dir>`` or # deprecated counterparts) may be passed to the DESTINATION options of @@ -161,6 +162,18 @@ # # Additionally, ``CMAKE_INSTALL_DEFAULT_COMPONENT_NAME`` will be set to # ``${PROJECT_NAME}`` to provide a sensible default for this CMake option. +# +# Note that mixing absolute and relative paths, particularly for ``BINDIR``, +# ``LIBDIR`` and ``INCLUDEDIR``, can cause issues with exported targets. Given +# that the default values for these are relative paths, relative paths should +# be used on the command line when possible (eg: use +# ``-DKDE_INSTALL_LIBDIR=lib64`` instead of +# ``-DKDE_INSTALL_LIBDIR=/usr/lib/lib64`` to override the library directory). +# +# 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. #============================================================================= # Copyright 2014-2015 Alex Merry <alex.merry@kde.org> @@ -564,6 +577,19 @@ _define_relative(AUTOSTARTDIR CONFDIR "autostart" "autostart files" AUTOSTART_INSTALL_DIR) +set(_mixed_core_path_styles FALSE) +if (IS_ABSOLUTE "${KDE_INSTALL_BINDIR}") + if (NOT IS_ABSOLUTE "${KDE_INSTALL_LIBDIR}" OR NOT IS_ABSOLUTE "${KDE_INSTALL_INCLUDEDIR}") + set(_mixed_core_path_styles ) + endif() +else() + if (IS_ABSOLUTE "${KDE_INSTALL_LIBDIR}" OR IS_ABSOLUTE "${KDE_INSTALL_INCLUDEDIR}") + set(_mixed_core_path_styles TRUE) + endif() +endif() +if (_mixed_core_path_styles) + message(WARNING "KDE_INSTALL_BINDIR, KDE_INSTALL_LIBDIR and KDE_INSTALL_INCLUDEDIR should either all be absolute paths or all be relative paths.") +endif() # For more documentation see above. diff --git a/modules/ECMAddAppIcon.cmake b/modules/ECMAddAppIcon.cmake new file mode 100644 index 00000000..f90d4c33 --- /dev/null +++ b/modules/ECMAddAppIcon.cmake @@ -0,0 +1,229 @@ +#.rst: +# ECMAddAppIcon +# ------------- +# +# Add icons to executable files and packages. +# +# :: +# +# ecm_add_app_icon(<sources_var> +# ICONS <icon> [<icon> [...]]) +# +# The given icons, whose names must match the pattern:: +# +# <size>-<other_text>.png +# +# will be added to the executable target whose sources are specified by +# ``<sources_var>`` on platforms that support it (Windows and Mac OS X). +# +# ``<size>`` is a numeric pixel size (typically 16, 32, 48, 64, 128 or 256). +# ``<other_text>`` can be any other text. See the platform notes below for any +# recommendations about icon sizes. +# +# Windows notes +# * Icons are compiled into the executable using a resource file. +# * Icons may not show up in Windows Explorer if the executable +# target does not have the ``WIN32_EXECUTABLE`` property set. +# * The tool png2ico is required. See :find-module:`FindPng2Ico`. +# * Supported sizes: 16, 32, 48, 64, 128. +# +# Mac OS X notes +# * The executable target must have the ``MACOSX_BUNDLE`` property set. +# * Icons are added to the bundle. +# * The tool iconutil (provided by Apple) is required. +# * Supported sizes: 16, 32, 64, 128, 256, 512, 1024. +# * At least a 128x128px icon is required. +# * Larger sizes are automatically used to substitute for smaller sizes on +# "Retina" (high-resolution) displays. For example, a 32px icon, if +# provided, will be used as a 32px icon on standard-resolution displays, +# and as a 16px-equivalent icon (with an "@2x" tag) on high-resolution +# displays. +# * This function sets the ``MACOSX_BUNDLE_ICON_FILE`` variable to the name +# of the generated icns file, so that it will be used as the +# ``MACOSX_BUNDLE_ICON_FILE`` target property when you call +# ``add_executable``. +# +# Since 1.7.0. + +#============================================================================= +# Copyright 2014 Alex Merry <alex.merry@kde.org> +# Copyright 2014 Ralf Habacker <ralf.habacker@freenet.de> +# Copyright 2006-2009 Alexander Neundorf, <neundorf@kde.org> +# Copyright 2006, 2007, Laurent Montel, <montel@kde.org> +# Copyright 2007 Matthias Kretz <kretz@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +# License text for the above reference.) + +include(CMakeParseArguments) + +function(ecm_add_app_icon appsources) + set(options) + set(oneValueArgs) + set(multiValueArgs ICONS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_ICONS) + message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon") + endif() + if(ARG_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unexpected arguments to ecm_add_app_icon: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + set(known_sizes 16 32 48 64 128 256 512 1024) + foreach(size ${known_sizes}) + set(icons_at_${size}px) + endforeach() + + foreach(icon ${ARG_ICONS}) + if (NOT EXISTS "${icon}") + message(AUTHOR_WARNING "${icon} does not exist, ignoring") + else() + string(REGEX MATCH "([0-9]+)\\-[^/]+\\.([a-z]+)$" + _dummy "${icon}") + set(size "${CMAKE_MATCH_1}") + set(ext "${CMAKE_MATCH_2}") + if (NOT size) + message(AUTHOR_WARNING "${icon} is not named correctly for ecm_add_app_icon - ignoring") + elseif (NOT ext STREQUAL "png") + message(AUTHOR_WARNING "${icon} is not a png file - ignoring") + else() + list(FIND known_sizes "${size}" offset) + if (offset GREATER -1) + list(APPEND icons_at_${size}px "${icon}") + endif() + endif() + endif() + endforeach() + + set(mac_icons ${icons_at_16px} + ${icons_at_32px} + ${icons_at_64px} + ${icons_at_128px} + ${icons_at_256px} + ${icons_at_512px} + ${icons_at_1024px}) + if (NOT icons_at_128px) + message(AUTHOR_WARNING "No 128px icon provided; this will not work on Mac OS X") + endif() + + set(windows_icons ${icons_at_16px} + ${icons_at_32px} + ${icons_at_48px} + ${icons_at_64px} + ${icons_at_128px}) + if (NOT windows_icons) + message(AUTHOR_WARNING "No icons suitable for use on Windows provided") + endif() + + set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${appsources}") + + if (WIN32 AND windows_icons) + set(saved_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}") + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_FIND_MODULE_DIR}) + find_package(Png2Ico) + set(CMAKE_MODULE_PATH "${saved_CMAKE_MODULE_PATH}") + + if (Png2Ico_FOUND) + if (Png2Ico_HAS_RCFILE_ARGUMENT) + add_custom_command( + OUTPUT "${_outfilename}.rc" "${_outfilename}.ico" + COMMAND Png2Ico::Png2Ico + ARGS + --rcfile "${_outfilename}.rc" + "${_outfilename}.ico" + ${windows_icons} + DEPENDS ${windows_icons} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + else() + add_custom_command( + OUTPUT "${_outfilename}.ico" + COMMAND Png2Ico::Png2Ico + ARGS "${_outfilename}.ico" ${windows_icons} + DEPENDS ${windows_icons} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + # this bit's a little hacky to make the dependency stuff work + file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n") + add_custom_command( + OUTPUT "${_outfilename}.rc" + COMMAND ${CMAKE_COMMAND} + ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc" + DEPENDS "${_outfilename}.ico" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + endif() + set(${appsources} "${${appsources}};${_outfilename}.rc" PARENT_SCOPE) + else() + message(WARNING "Unable to find the png2ico utility - application will not have an application icon!") + endif() + elseif (APPLE AND mac_icons) + # first generate .iconset directory structure, then convert to .icns format using the Mac OS X "iconutil" utility, + # to create retina compatible icon, you need png source files in pixel resolution 16x16, 32x32, 64x64, 128x128, + # 256x256, 512x512, 1024x1024 + find_program(ICONUTIL_EXECUTABLE NAMES iconutil) + if (ICONUTIL_EXECUTABLE) + add_custom_command( + OUTPUT "${_outfilename}.iconset" + COMMAND ${CMAKE_COMMAND} + ARGS -E make_directory "${_outfilename}.iconset" + ) + set(iconset_icons) + macro(copy_icon filename sizename) + add_custom_command( + OUTPUT "${_outfilename}.iconset/icon_${sizename}.png" + COMMAND ${CMAKE_COMMAND} + ARGS -E copy + "${filename}" + "${_outfilename}.iconset/icon_${sizename}.png" + DEPENDS + "${_outfilename}.iconset" + "${filename}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + list(APPEND iconset_icons + "${_outfilename}.iconset/icon_${sizename}.png") + endmacro() + foreach(size 16 32 64 128 256 512) + math(EXPR double_size "2 * ${size}") + foreach(file ${icons_at_${size}px}) + copy_icon("${file}" "${size}x${size}") + endforeach() + foreach(file ${icons_at_${double_size}px}) + copy_icon("${file}" "${size}x${size}@2x") + endforeach() + endforeach() + + # generate .icns icon file + add_custom_command( + OUTPUT "${_outfilename}.icns" + COMMAND ${ICONUTIL_EXECUTABLE} + ARGS + --convert icns + --output "${_outfilename}.icns" + "${_outfilename}.iconset" + DEPENDS ${iconset_icons} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + # This will register the icon into the bundle + set(MACOSX_BUNDLE_ICON_FILE ${appsources}.icns PARENT_SCOPE) + + # Append the icns file to the sources list so it will be a dependency to the + # main target + set(${appsources} "${${appsources}};${_outfilename}.icns" PARENT_SCOPE) + + # Install the icon into the Resources dir in the bundle + set_source_files_properties(${_outfilename}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + else(ICONUTIL_EXECUTABLE) + message(STATUS "Unable to find the iconutil utility - application will not have an application icon!") + endif(ICONUTIL_EXECUTABLE) + endif() +endfunction() diff --git a/modules/ECMAddTests.cmake b/modules/ECMAddTests.cmake index ed1e0f66..e9e2fc53 100644 --- a/modules/ECMAddTests.cmake +++ b/modules/ECMAddTests.cmake @@ -2,43 +2,59 @@ # ECMAddTests # ----------- # -# Add test executables. +# Convenience functions for adding tests. # # :: # -# ecm_add_test(<sources> LINK_LIBRARIES <library> [<library> [...]] -# [TEST_NAME <name>] -# [NAME_PREFIX <prefix>] -# [GUI]) +# ecm_add_tests(<sources> LINK_LIBRARIES <library> [<library> [...]] +# [NAME_PREFIX <prefix>] +# [GUI] +# [TARGET_NAMES_VAR <target_names_var>] +# [TEST_NAMES_VAR <test_names_var>]) # -# Add a new unit test using the passed source files. The parameter TEST_NAME is -# used to set the name of the resulting test, and the target built for and run -# by the test. It may be omitted if there is exactly one source file. In that -# case the name of the source file (without the file extension) will be used as -# the test name. +# A convenience function for adding multiple tests, each consisting of a +# single source file. For each file in <sources>, an executable target will be +# created (the name of which will be the basename of the source file). This +# will be linked against the libraries given with LINK_LIBRARIES. Each +# executable will be added as a test with the same name. # -# If NAME_PREFIX is given, this prefix will be prepended to the test name, but -# not the target name. As a result, it will not prevent clashes between tests +# If NAME_PREFIX is given, this prefix will be prepended to the test names, but +# not the target names. As a result, it will not prevent clashes between tests # with the same name in different parts of the project, but it can be used to # give an indication of where to look for a failing test. # -# If the flag GUI is passed the test binary will be a GUI executable, otherwise -# the resulting binary will be a console application. The test will be linked -# against the libraries and/or targets passed to LINK_LIBRARIES. +# If the flag GUI is passed the test binaries will be GUI executables, otherwise +# the resulting binaries will be console applications (regardless of the value +# of CMAKE_WIN32_EXECUTABLE or CMAKE_MACOSX_BUNDLE). Be aware that this changes +# the executable entry point on Windows (although some frameworks, such as Qt, +# abstract this difference away). +# +# The TARGET_NAMES_VAR and TEST_NAMES_VAR arguments, if given, should specify a +# variable name to receive the list of generated target and test names, +# respectively. This makes it convenient to apply properties to them as a +# whole, for example, using set_target_properties() or set_tests_properties(). # +# The generated target executables will have the effects of ecm_mark_as_test() +# (from the :module:`ECMMarkAsTest` module) applied to it. # # :: # -# ecm_add_tests(<sources> LINK_LIBRARIES <library> [<library> [...]] -# [NAME_PREFIX <prefix>] -# [GUI]) +# ecm_add_test(<sources> LINK_LIBRARIES <library> [<library> [...]] +# [TEST_NAME <name>] +# [NAME_PREFIX <prefix>] +# [GUI]) +# +# This is a single-test form of ecm_add_tests that allows multiple source files +# to be used for a single test. If using multiple source files, TEST_NAME must +# be given; this will be used for both the target and test names (and, as with +# ecm_add_tests(), the NAME_PREFIX argument will be prepended to the test name). +# # -# This is a convenient version of ecm_add_test() for when you have many tests -# that consist of a single source file each. It behaves like calling -# ecm_add_test() once for each source file, with the same named arguments. +# Since pre-1.0.0. #============================================================================= # Copyright 2013 Alexander Richardson <arichardson.kde@gmail.com> +# Copyright 2015 Alex Merry <alex.merry@kde.org> # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file COPYING-CMAKE-SCRIPTS for details. @@ -50,18 +66,21 @@ # (To distribute this file outside of extra-cmake-modules, substitute the full # License text for the above reference.) +include(CMakeParseArguments) include(ECMMarkAsTest) include(ECMMarkNonGuiExecutable) function(ecm_add_test) set(options GUI) - set(oneValueArgs TEST_NAME NAME_PREFIX) + # TARGET_NAME_VAR and TEST_NAME_VAR are undocumented args used by + # ecm_add_tests + set(oneValueArgs TEST_NAME NAME_PREFIX TARGET_NAME_VAR TEST_NAME_VAR) set(multiValueArgs LINK_LIBRARIES) - cmake_parse_arguments(ECM_ADD_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - set(_sources ${ECM_ADD_TEST_UNPARSED_ARGUMENTS}) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(_sources ${ARG_UNPARSED_ARGUMENTS}) list(LENGTH _sources _sourceCount) - if(ECM_ADD_TEST_TEST_NAME) - set(_targetname ${ECM_ADD_TEST_TEST_NAME}) + if(ARG_TEST_NAME) + set(_targetname ${ARG_TEST_NAME}) elseif(${_sourceCount} EQUAL "1") #use the source file name without extension as the testname get_filename_component(_targetname ${_sources} NAME_WE) @@ -70,31 +89,53 @@ function(ecm_add_test) message(FATAL_ERROR "ecm_add_test() called with multiple source files but without setting \"TEST_NAME\"") endif() - set(_testname "${ECM_ADD_TEST_NAME_PREFIX}${_targetname}") - add_executable(${_targetname} ${_sources}) - if(NOT ECM_ADD_TEST_GUI) + set(_testname ${ARG_NAME_PREFIX}${_targetname}) + set(gui_args) + if(ARG_GUI) + set(gui_args WIN32 MACOSX_BUNDLE) + endif() + add_executable(${_targetname} ${gui_args} ${_sources}) + if(NOT ARG_GUI) ecm_mark_nongui_executable(${_targetname}) endif() add_test(NAME ${_testname} COMMAND ${_targetname}) - target_link_libraries(${_targetname} ${ECM_ADD_TEST_LINK_LIBRARIES}) + target_link_libraries(${_targetname} ${ARG_LINK_LIBRARIES}) ecm_mark_as_test(${_targetname}) + if (ARG_TARGET_NAME_VAR) + set(${ARG_TARGET_NAME_VAR} "${_targetname}" PARENT_SCOPE) + endif() + if (ARG_TEST_NAME_VAR) + set(${ARG_TEST_NAME_VAR} "${_testname}" PARENT_SCOPE) + endif() endfunction() function(ecm_add_tests) set(options GUI) - set(oneValueArgs NAME_PREFIX) + set(oneValueArgs NAME_PREFIX TARGET_NAMES_VAR TEST_NAMES_VAR) set(multiValueArgs LINK_LIBRARIES) - cmake_parse_arguments(ECM_ADD_TESTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - if(ECM_ADD_TESTS_GUI) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(ARG_GUI) set(_exe_type GUI) else() set(_exe_type "") endif() - foreach(_test_source ${ECM_ADD_TESTS_UNPARSED_ARGUMENTS}) + set(test_names) + set(target_names) + foreach(_test_source ${ARG_UNPARSED_ARGUMENTS}) ecm_add_test(${_test_source} - NAME_PREFIX ${ECM_ADD_TESTS_NAME_PREFIX} - LINK_LIBRARIES ${ECM_ADD_TESTS_LINK_LIBRARIES} - ${_exe_type} + NAME_PREFIX ${ARG_NAME_PREFIX} + LINK_LIBRARIES ${ARG_LINK_LIBRARIES} + TARGET_NAME_VAR target_name + TEST_NAME_VAR test_name + ${_exe_type} ) + list(APPEND _test_names "${test_name}") + list(APPEND _target_names "${target_name}") endforeach() + if (ARG_TARGET_NAMES_VAR) + set(${ARG_TARGET_NAMES_VAR} "${_target_names}" PARENT_SCOPE) + endif() + if (ARG_TEST_NAMES_VAR) + set(${ARG_TEST_NAMES_VAR} "${_test_names}" PARENT_SCOPE) + endif() endfunction() diff --git a/modules/ECMCoverageOption.cmake b/modules/ECMCoverageOption.cmake index 8d435de8..4c1db9de 100644 --- a/modules/ECMCoverageOption.cmake +++ b/modules/ECMCoverageOption.cmake @@ -2,19 +2,20 @@ # ECMCoverageOption # -------------------- # -# Creates a BUILD_COVERAGE option, so the project can be built with code coverage -# support. +# Allow users to easily enable GCov code coverage support. # -# :: +# Code coverage allows you to check how much of your codebase is covered by +# your tests. This module makes it easy to build with support for +# `GCov <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`_. # -# BUILD_COVERAGE -# -# If it's on, the project will be compiled with code coverage support, using -# gcov. Otherwise, it will be built normally. -# -# :: +# When this module is included, a ``BUILD_COVERAGE`` option is added (default +# OFF). Turning this option on enables GCC's coverage instrumentation, and +# links against ``libgcov``. # +# Note that this will probably break the build if you are not using GCC. # +# Since 1.3.0. + #============================================================================= # Copyright 2014 Aleix Pol Gonzalez <aleixpol@kde.org> # diff --git a/modules/ECMCreateQmFromPoFiles.cmake b/modules/ECMCreateQmFromPoFiles.cmake index b66e5989..b4194723 100644 --- a/modules/ECMCreateQmFromPoFiles.cmake +++ b/modules/ECMCreateQmFromPoFiles.cmake @@ -68,6 +68,8 @@ # # This generates a C++ file which loads "mylib.qm" at startup, assuming it has # been installed by ecm_create_qm_from_po_files(), and compiles it into ``mylib``. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Aurélien Gâteau <agateau@kde.org> @@ -108,13 +110,18 @@ endfunction() function(_ECM_QM_CREATE_TARGET install_destination catalog_name) # Find lconvert - get_target_property(lrelease_location Qt5::lrelease LOCATION) - get_filename_component(lrelease_path ${lrelease_location} PATH) - find_program(lconvert_executable - NAMES lconvert-qt5 lconvert - PATHS ${lrelease_path} - NO_DEFAULT_PATH - ) + if(TARGET Qt5::lconvert) + set(lconvert_executable Qt5::lconvert) + else() + # Qt < 5.3.1 does not define Qt5::lconvert + get_target_property(lrelease_location Qt5::lrelease LOCATION) + get_filename_component(lrelease_path ${lrelease_location} PATH) + find_program(lconvert_executable + NAMES lconvert-qt5 lconvert + PATHS ${lrelease_path} + NO_DEFAULT_PATH + ) + endif() if (catalog_name) set(install_args RENAME ${catalog_name}.qm) @@ -138,7 +145,7 @@ function(_ECM_QM_CREATE_TARGET install_destination catalog_name) COMMAND ${lconvert_executable} ARGS -i ${it} -o ${tsfile} -target-language ${language} COMMAND Qt5::lrelease - ARGS -compress -removeidentical -silent ${tsfile} -qm ${qmfile} + ARGS -removeidentical -silent ${tsfile} -qm ${qmfile} DEPENDS ${it} ) install( diff --git a/modules/ECMEnableSanitizers.cmake b/modules/ECMEnableSanitizers.cmake index a0df80e2..e64599b6 100644 --- a/modules/ECMEnableSanitizers.cmake +++ b/modules/ECMEnableSanitizers.cmake @@ -2,9 +2,10 @@ # ECMEnableSanitizers # ------------------- # -# Enable compiler sanitizer flags +# Enable compiler sanitizer flags. +# +# The following sanitizers are supported: # -# The following sanitizers are supported : # - Address Sanitizer # - Memory Sanitizer # - Thread Sanitizer @@ -14,53 +15,59 @@ # All of them are implemented in Clang, depending on your version, and # there is an work in progress in GCC, where some of them are currently # implemented. -# This module will check your current compiler version to see if it support -# the sanitizers that you want to enable # -# How to use it ? -# --------------- -# This module is included in KDECompilerSettings. Therefore you don't have -# to change your CMakeLists.txt +# This module will check your current compiler version to see if it +# supports the sanitizers that you want to enable +# +# Usage +# ===== +# +# Simply add:: +# +# include(ECMEnableSanitizers) +# +# to your ``CMakeLists.txt``. Note that this module is included in +# KDECompilerSettings, so projects using that module do not need to also +# include this one. # -# It introduce a new cached variable : -# ECM_ENABLE_SANITIZERS +# The sanitizers are not enabled by default. Instead, you must set +# ``ECM_ENABLE_SANITIZERS`` (either in your ``CMakeLists.txt`` or on the +# command line) to a semicolon-separated list of sanitizers you wish to enable. +# The options are: # -# which can take the following values : # - address # - memory # - thread # - leak # - undefined # -# You can enable two sanitizers in the same build, depending on their -# compatibility by separating each one with a semicolon : -# ECM_ENABLE_SANITIZERS='address;undefined' +# The sanitizers "address", "memory" and "thread" are mutually exclusive. You +# cannot enable two of them in the same build. # +# "leak" requires the "address" sanitizer. # -# The sanitizers `address`, `memory` and `thread` are mutually exclusive. -# You cannot enable two of them in the same build. +# .. note:: # -# `undefined` can be used with every other sanitizers +# To reduce the overhead induced by the instrumentation of the sanitizers, it +# is advised to enable compiler optimizations (``-O1`` or higher). # -# `leak` can be enable with the `address` sanitizer. +# Example +# ======= # -# Finally, to reduce the overhead induced by the instrumentation of the -# sanitizers, it is advised to use -O1, or higher to improve the performances. +# This is an example of usage:: # -# Example -# ------- -# This is an example of usage : -# mkdir _build -# cd _build -# cmake -DECM_ENABLE_SANITIZERS='address' .. +# mkdir build +# cd build +# cmake -DECM_ENABLE_SANITIZERS='address;leak;undefined' .. # -# If you want to use multiple sanitizers +# .. note:: # -# cmake -DECM_ENABLE_SANITIZERS='address;leak;undefined' .. +# Most of the sanitizers will require Clang. To enable it, use:: # -# => Most of the sanitizers will require Clang. To enable it, use : -# -DCMAKE_CXX_COMPILER=clang++ +# -DCMAKE_CXX_COMPILER=clang++ # +# Since 1.3.0. + #============================================================================= # Copyright 2014 Mathieu Tarral <mathieu.tarral@gmail.com> # @@ -118,7 +125,7 @@ macro (enable_sanitizer_flags sanitize_option) set(XSAN_COMPILE_FLAGS "-fsanitize=leak") set(XSAN_LINKER_FLAGS "lsan") elseif (${sanitize_option} MATCHES "undefined") - check_compiler_version("99.99" "3.1") + check_compiler_version("4.9" "3.1") set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls") else () message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.") diff --git a/modules/ECMFindModuleHelpers.cmake b/modules/ECMFindModuleHelpers.cmake index 79bd6fb8..63cccb93 100644 --- a/modules/ECMFindModuleHelpers.cmake +++ b/modules/ECMFindModuleHelpers.cmake @@ -92,6 +92,8 @@ # different components (typically because of multiple find_package() calls) then # ``<name>_TARGETS``, for example, will contain all the targets found in any # call (although no duplicates). +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> diff --git a/modules/ECMGenerateHeaders.cmake b/modules/ECMGenerateHeaders.cmake index bac50869..cefc82df 100644 --- a/modules/ECMGenerateHeaders.cmake +++ b/modules/ECMGenerateHeaders.cmake @@ -6,26 +6,35 @@ # # :: # -# ecm_generate_headers(<camelcase_headers_var> -# HEADER_NAMES <CamelCaseHeader> [<CamelCaseHeader> [...]] +# ecm_generate_headers(<camelcase_forwarding_headers_var> +# HEADER_NAMES <CamelCaseName> [<CamelCaseName> [...]] +# [ORIGINAL <CAMELCASE|LOWERCASE>] # [OUTPUT_DIR <output_dir>] # [PREFIX <prefix>] # [REQUIRED_HEADERS <variable>] +# [COMMON_HEADER <HeaderName>] # [RELATIVE <relative_path>]) # # For each CamelCase header name passed to HEADER_NAMES, a file of that name -# will be generated that will include a lowercased version with ``.h`` appended. -# For example, the header ``ClassA`` will include ``classa.h``. The file -# locations of these generated headers will be stored in -# <camelcase_headers_var>. -# -# PREFIX places the headers in subdirectories. This should be a CamelCase name -# like KParts, which will cause the CamelCase headers to be placed in the KParts -# directory (eg: KParts/Part). It will also, for the convenience of code in the -# source distribution, generate forwarding lowercase headers, like -# kparts/part.h. This allows includes like "#include <kparts/part.h>" to be -# used before installation, as long as the include_directories are set -# appropriately. +# will be generated that will include a version with ``.h`` appended. +# For example, the generated header ``ClassA`` will include ``classa.h`` (or +# ``ClassA.h``, see ORIGINAL). +# If a CamelCaseName consists of multiple comma-separated files, e.g. +# ``ClassA,ClassB,ClassC``, then multiple camelcase header files will be +# generated which are redirects to the first header file. +# The file locations of these generated headers will be stored in +# <camelcase_forwarding_headers_var>. +# +# ORIGINAL specifies how the name of the original header is written: lowercased +# or also camelcased. The default is LOWERCASE. Since 1.8.0. +# +# PREFIX places the generated headers in subdirectories. This should be a +# CamelCase name like ``KParts``, which will cause the CamelCase forwarding +# headers to be placed in the ``KParts`` directory (e.g. ``KParts/Part``). It +# will also, for the convenience of code in the source distribution, generate +# forwarding headers based on the original names (e.g. ``kparts/part.h``). This +# allows includes like ``"#include <kparts/part.h>"`` to be used before +# installation, as long as the include_directories are set appropriately. # # OUTPUT_DIR specifies where the files will be generated; this should be within # the build directory. By default, ``${CMAKE_CURRENT_BINARY_DIR}`` will be used. @@ -35,14 +44,17 @@ # headers will be appended so that they can be installed together with the # generated ones. This is mostly intended as a convenience so that adding a new # header to a project only requires specifying the CamelCase variant in the -# CMakeLists.txt file; the lowercase variant will then be added to this +# CMakeLists.txt file; the original variant will then be added to this # variable. # -# The RELATIVE argument indicates where the lowercase headers can be found +# COMMON_HEADER generates an additional convenience header which includes all +# other header files. +# +# The RELATIVE argument indicates where the original headers can be found # relative to CMAKE_CURRENT_SOURCE_DIR. It does not affect the generated -# CamelCase files, but ecm_generate_headers() uses it when checking that the -# lowercase header exists, and to generate lowercase forwarding headers when -# PREFIX is set. +# CamelCase forwarding files, but ecm_generate_headers() uses it when checking +# that the original header exists, and to generate originally named forwarding +# headers when PREFIX is set. # # To allow other parts of the source distribution (eg: tests) to use the # generated headers before installation, it may be desirable to set the @@ -64,6 +76,7 @@ # MLBar # # etc # REQUIRED_HEADERS MyLib_HEADERS +# COMMON_HEADER MLGeneral # ) # install(FILES ${MyLib_FORWARDING_HEADERS} ${MyLib_HEADERS} # DESTINATION ${CMAKE_INSTALL_PREFIX}/include @@ -77,7 +90,9 @@ # MyLib_FORWARDING_HEADERS # HEADERS # Foo -# Bar +# # several classes are contained in bar.h, so generate +# # additional files +# Bar,BarList # # etc # PREFIX MyLib # REQUIRED_HEADERS MyLib_HEADERS @@ -88,10 +103,13 @@ # install(FILES ${MyLib_HEADERS} # DESTINATION ${CMAKE_INSTALL_PREFIX}/include/mylib # COMPONENT Devel) +# +# Since pre-1.0.0. #============================================================================= # Copyright 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com> # Copyright 2014 Alex Merry <alex.merry@kdemail.net> +# Copyright 2015 Patrick Spendrin <patrick.spendrin@kdab.com> # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file COPYING-CMAKE-SCRIPTS for details. @@ -105,9 +123,9 @@ include(CMakeParseArguments) -function(ECM_GENERATE_HEADERS camelcase_headers_var) +function(ECM_GENERATE_HEADERS camelcase_forwarding_headers_var) set(options) - set(oneValueArgs OUTPUT_DIR PREFIX REQUIRED_HEADERS RELATIVE) + set(oneValueArgs ORIGINAL OUTPUT_DIR PREFIX REQUIRED_HEADERS COMMON_HEADER RELATIVE) set(multiValueArgs HEADER_NAMES) cmake_parse_arguments(EGH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -119,6 +137,14 @@ function(ECM_GENERATE_HEADERS camelcase_headers_var) message(FATAL_ERROR "Missing header_names argument to ECM_GENERATE_HEADERS") endif() + if(NOT EGH_ORIGINAL) + # default + set(EGH_ORIGINAL "LOWERCASE") + endif() + if(NOT EGH_ORIGINAL STREQUAL "LOWERCASE" AND NOT EGH_ORIGINAL STREQUAL "CAMELCASE") + message(FATAL_ERROR "Unexpected value for original argument to ECM_GENERATE_HEADERS: ${EGH_ORIGINAL}") + endif() + if(NOT EGH_OUTPUT_DIR) set(EGH_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") endif() @@ -132,34 +158,64 @@ function(ECM_GENERATE_HEADERS camelcase_headers_var) if (NOT "${EGH_PREFIX}" MATCHES "^.*/$") set(EGH_PREFIX "${EGH_PREFIX}/") endif() - string(TOLOWER "${EGH_PREFIX}" lowercaseprefix) + if (EGH_ORIGINAL STREQUAL "CAMELCASE") + set(originalprefix "${EGH_PREFIX}") + else() + string(TOLOWER "${EGH_PREFIX}" originalprefix) + endif() endif() - foreach(_CLASSNAME ${EGH_HEADER_NAMES}) - string(TOLOWER "${_CLASSNAME}" lowercaseclassname) - set(FANCY_HEADER_FILE "${EGH_OUTPUT_DIR}/${EGH_PREFIX}${_CLASSNAME}") - set(_actualheader "${CMAKE_CURRENT_SOURCE_DIR}/${EGH_RELATIVE}${lowercaseclassname}.h") + foreach(_classnameentry ${EGH_HEADER_NAMES}) + string(REPLACE "," ";" _classnames ${_classnameentry}) + list(GET _classnames 0 _baseclass) + + if (EGH_ORIGINAL STREQUAL "CAMELCASE") + set(originalbasename "${_baseclass}") + else() + string(TOLOWER "${_baseclass}" originalbasename) + endif() + + set(_actualheader "${CMAKE_CURRENT_SOURCE_DIR}/${EGH_RELATIVE}${originalbasename}.h") if (NOT EXISTS ${_actualheader}) message(FATAL_ERROR "Could not find \"${_actualheader}\"") endif() - if (NOT EXISTS ${FANCY_HEADER_FILE}) - file(WRITE ${FANCY_HEADER_FILE} "#include \"${lowercaseprefix}${lowercaseclassname}.h\"\n") - endif() - list(APPEND ${camelcase_headers_var} "${FANCY_HEADER_FILE}") - if (EGH_REQUIRED_HEADERS) - list(APPEND ${EGH_REQUIRED_HEADERS} "${_actualheader}") - endif() - if (EGH_PREFIX) - # Local forwarding header, for namespaced headers, e.g. kparts/part.h - set(REGULAR_HEADER_NAME ${EGH_OUTPUT_DIR}/${lowercaseprefix}${lowercaseclassname}.h) - if (NOT EXISTS ${REGULAR_HEADER_NAME}) - file(WRITE ${REGULAR_HEADER_NAME} "#include \"${_actualheader}\"\n") + + foreach(_CLASSNAME ${_classnames}) + set(FANCY_HEADER_FILE "${EGH_OUTPUT_DIR}/${EGH_PREFIX}${_CLASSNAME}") + if (NOT EXISTS ${FANCY_HEADER_FILE}) + file(WRITE ${FANCY_HEADER_FILE} "#include \"${originalprefix}${originalbasename}.h\"\n") endif() - endif() + list(APPEND ${camelcase_forwarding_headers_var} "${FANCY_HEADER_FILE}") + if (EGH_PREFIX) + # Local forwarding header, for namespaced headers, e.g. kparts/part.h + if(EGH_ORIGINAL STREQUAL "CAMELCASE") + set(originalclassname "${_CLASSNAME}") + else() + string(TOLOWER "${_CLASSNAME}" originalclassname) + endif() + set(REGULAR_HEADER_NAME ${EGH_OUTPUT_DIR}/${originalprefix}${originalclassname}.h) + if (NOT EXISTS ${REGULAR_HEADER_NAME}) + file(WRITE ${REGULAR_HEADER_NAME} "#include \"${_actualheader}\"\n") + endif() + endif() + endforeach() + + list(APPEND _REQUIRED_HEADERS "${_actualheader}") endforeach() - set(${camelcase_headers_var} ${${camelcase_headers_var}} PARENT_SCOPE) + if(EGH_COMMON_HEADER) + #combine required headers into 1 big convenience header + set(COMMON_HEADER ${EGH_OUTPUT_DIR}/${EGH_PREFIX}${EGH_COMMON_HEADER}) + file(WRITE ${COMMON_HEADER} "// convenience header\n") + foreach(_header ${_REQUIRED_HEADERS}) + get_filename_component(_base ${_header} NAME) + file(APPEND ${COMMON_HEADER} "#include \"${_base}\"\n") + endforeach() + list(APPEND ${camelcase_forwarding_headers_var} "${COMMON_HEADER}") + endif() + + set(${camelcase_forwarding_headers_var} ${${camelcase_forwarding_headers_var}} PARENT_SCOPE) if (NOT EGH_REQUIRED_HEADERS STREQUAL "") - set(${EGH_REQUIRED_HEADERS} ${${EGH_REQUIRED_HEADERS}} PARENT_SCOPE) + set(${EGH_REQUIRED_HEADERS} ${${EGH_REQUIRED_HEADERS}} ${_REQUIRED_HEADERS} PARENT_SCOPE) endif () endfunction() diff --git a/modules/ECMGeneratePkgConfigFile.cmake b/modules/ECMGeneratePkgConfigFile.cmake index eb0e385d..eaef7b41 100644 --- a/modules/ECMGeneratePkgConfigFile.cmake +++ b/modules/ECMGeneratePkgConfigFile.cmake @@ -1,8 +1,11 @@ #.rst: # ECMGeneratePkgConfigFile -# ------------------ +# ------------------------ # -# Generate a ``.pc`` file for the benefit of autotools-based projects. +# Generate a `pkg-config <http://www.freedesktop.org/wiki/Software/pkg-config/>`_ +# file for the benefit of +# `autotools <http://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html>`_-based +# projects. # # :: # @@ -15,38 +18,41 @@ # [DEFINES -D<variable=value>...] # [INSTALL]) # -# BASE_NAME is the name of the module. It's the name projects will use to find -# the module. +# ``BASE_NAME`` is the name of the module. It's the name projects will use to +# find the module. # -# LIB_NAME is the name of the library that is being exported. If undefined, it -# will default to the BASE_NAME. That means the LIB_NAME will be set as the name -# field as well as the library to link to. +# ``LIB_NAME`` is the name of the library that is being exported. If undefined, +# it will default to the ``BASE_NAME``. That means the ``LIB_NAME`` will be set +# as the name field as well as the library to link to. # -# FILENAME_VAR is specified with a variable name. This variable will receive the -# location of the generated file will be set, within the build directory. This -# way it can be used in case some processing is required. See also INSTALL. +# ``FILENAME_VAR`` is specified with a variable name. This variable will +# receive the location of the generated file will be set, within the build +# directory. This way it can be used in case some processing is required. See +# also ``INSTALL``. # -# INCLUDE_INSTALL_DIR specifies where the includes will be installed. If it's not -# specified, it will default to INSTALL_INCLUDEDIR, CMAKE_INSTALL_INCLUDEDIR or just -# "include/" in case they are specified, with the BASE_NAME postfixed. +# ``INCLUDE_INSTALL_DIR`` specifies where the includes will be installed. If +# it's not specified, it will default to ``INSTALL_INCLUDEDIR``, +# ``CMAKE_INSTALL_INCLUDEDIR`` or just "include/" in case they are specified, +# with the BASE_NAME postfixed. # -# LIB_INSTALL_DIR specifies where the library is being installed. If it's not -# specified, it will default to LIB_INSTALL_DIR, CMAKE_INSTALL_LIBDIR or just -# "lib/" in case they are specified. +# ``LIB_INSTALL_DIR`` specifies where the library is being installed. If it's +# not specified, it will default to ``LIB_INSTALL_DIR``, +# ``CMAKE_INSTALL_LIBDIR`` or just "lib/" in case they are specified. # -# DEFINES is a list of preprocessor defines that it is recommended users of the -# library pass to the compiler when using it. +# ``DEFINES`` is a list of preprocessor defines that it is recommended users of +# the library pass to the compiler when using it. # -# INSTALL will cause the module to be installed to the ``pkgconfig`` subdirectory -# of LIB_INSTALL_DIR, unless the ECM_PKGCONFIG_INSTALL_DIR cache variable is set -# to something different. Note that the first call to ecm_generate_pkgconfig_file -# with the INSTALL argument will cause ECM_PKGCONFIG_INSTALL_DIR to be set to the -# cache, and will be used in any subsequent calls. -# -# To properly use this macro a version needs to be set. To retrieve it ``ECM_PKGCONFIG_INSTALL_DIR`` -# uses PROJECT_VERSION. To set it, use the project() command (only available since CMake 3.0) or the -# ecm_setup_version() macro. +# ``INSTALL`` will cause the module to be installed to the ``pkgconfig`` +# subdirectory of ``LIB_INSTALL_DIR``, unless the ``ECM_PKGCONFIG_INSTALL_DIR`` +# cache variable is set to something different. Note that the first call to +# ecm_generate_pkgconfig_file with the ``INSTALL`` argument will cause +# ``ECM_PKGCONFIG_INSTALL_DIR`` to be set to the cache, and will be used in any +# subsequent calls. # +# To properly use this macro a version needs to be set. To retrieve it, +# ``ECM_PKGCONFIG_INSTALL_DIR`` uses ``PROJECT_VERSION``. To set it, use the +# project() command (only available since CMake 3.0) or the ecm_setup_version() +# macro. # # Example usage: # @@ -59,6 +65,7 @@ # INSTALL # ) # +# Since 1.3.0. #============================================================================= # Copyright 2014 Aleix Pol Gonzalez <aleixpol@kde.org> diff --git a/modules/ECMGeneratePriFile.cmake b/modules/ECMGeneratePriFile.cmake index b353e867..af4b8771 100644 --- a/modules/ECMGeneratePriFile.cmake +++ b/modules/ECMGeneratePriFile.cmake @@ -68,6 +68,8 @@ # QT += KArchive # # in their ``.pro`` file. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 David Faure <faure@kde.org> @@ -156,16 +158,16 @@ function(ECM_GENERATE_PRI_FILE) file(GENERATE OUTPUT ${PRI_FILENAME} CONTENT - "QT.@PRI_TARGET_BASENAME@.VERSION = @PROJECT_VERSION_STRING@ -QT.@PRI_TARGET_BASENAME@.MAJOR_VERSION = @PROJECT_VERSION_MAJOR@ -QT.@PRI_TARGET_BASENAME@.MINOR_VERSION = @PROJECT_VERSION_MINOR@ -QT.@PRI_TARGET_BASENAME@.PATCH_VERSION = @PROJECT_VERSION_PATCH@ -QT.@PRI_TARGET_BASENAME@.name = @PRI_TARGET_LIBNAME@ -QT.@PRI_TARGET_BASENAME@.defines = @PRI_TARGET_DEFINES@ -QT.@PRI_TARGET_BASENAME@.includes = @PRI_TARGET_INCLUDES@ -QT.@PRI_TARGET_BASENAME@.private_includes = -QT.@PRI_TARGET_BASENAME@.libs = @PRI_TARGET_LIBS@ -QT.@PRI_TARGET_BASENAME@.depends = @PRI_TARGET_QTDEPS@ + "QT.${PRI_TARGET_BASENAME}.VERSION = ${PROJECT_VERSION_STRING} +QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PROJECT_VERSION_MAJOR} +QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PROJECT_VERSION_MINOR} +QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PROJECT_VERSION_PATCH} +QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME} +QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES} +QT.${PRI_TARGET_BASENAME}.includes = ${PRI_TARGET_INCLUDES} +QT.${PRI_TARGET_BASENAME}.private_includes = +QT.${PRI_TARGET_BASENAME}.libs = ${PRI_TARGET_LIBS} +QT.${PRI_TARGET_BASENAME}.depends = ${PRI_TARGET_QTDEPS} " ) endfunction() diff --git a/modules/ECMInstallIcons.cmake b/modules/ECMInstallIcons.cmake index 19d44d36..549ebe19 100644 --- a/modules/ECMInstallIcons.cmake +++ b/modules/ECMInstallIcons.cmake @@ -59,6 +59,8 @@ # # With this syntax, the file ``hi22-actions-menu_new.png`` would be installed # into ``<icon_install_dir>/hicolor/22x22/actions/menu_new.png`` +# +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> @@ -109,6 +111,8 @@ macro(_ecm_install_icons_v1 _defaultpath) set(_l10n_SUBDIR ".") endif(_lang) + set(_themes) + # first the png icons file(GLOB _icons *.png) foreach (_current_ICON ${_icons} ) @@ -121,6 +125,7 @@ macro(_ecm_install_icons_v1 _defaultpath) set(_theme_GROUP ${_ECM_ICON_THEME_${_type}}) if( _theme_GROUP) + list(APPEND _themes "${_theme_GROUP}") _ECM_ADD_ICON_INSTALL_RULE(${CMAKE_CURRENT_BINARY_DIR}/install_icons.cmake ${_defaultpath}/${_theme_GROUP}/${_size}x${_size} ${_group} ${_current_ICON} ${_name} ${_l10n_SUBDIR}) @@ -139,6 +144,7 @@ macro(_ecm_install_icons_v1 _defaultpath) set(_theme_GROUP ${_ECM_ICON_THEME_${_type}}) if( _theme_GROUP) + list(APPEND _themes "${_theme_GROUP}") _ECM_ADD_ICON_INSTALL_RULE(${CMAKE_CURRENT_BINARY_DIR}/install_icons.cmake ${_defaultpath}/${_theme_GROUP}/${_size}x${_size} ${_group} ${_current_ICON} ${_name} ${_l10n_SUBDIR}) @@ -156,13 +162,21 @@ macro(_ecm_install_icons_v1 _defaultpath) set(_theme_GROUP ${_ECM_ICON_THEME_${_type}}) if( _theme_GROUP) + list(APPEND _themes "${_theme_GROUP}") _ECM_ADD_ICON_INSTALL_RULE(${CMAKE_CURRENT_BINARY_DIR}/install_icons.cmake ${_defaultpath}/${_theme_GROUP}/scalable ${_group} ${_current_ICON} ${_name} ${_l10n_SUBDIR}) endif( _theme_GROUP) endforeach (_current_ICON) - _ecm_update_iconcache("${_defaultpath}" hicolor) + if (_themes) + list(REMOVE_DUPLICATES _themes) + foreach(_theme ${_themes}) + _ecm_update_iconcache("${_defaultpath}" "${_theme}") + endforeach() + else() + message(AUTHOR_WARNING "No suitably-named icons found") + endif() endmacro() @@ -184,7 +198,9 @@ endmacro() # Updates the mtime of the icon theme directory, so caches that # watch for changes to the directory will know to update. +# If present, this also runs gtk-update-icon-cache (which despite the name is also used by Qt). function(_ecm_update_iconcache installdir theme) + find_program(GTK_UPDATE_ICON_CACHE_EXECUTABLE NAMES gtk-update-icon-cache) # We don't always have touch command (e.g. on Windows), so instead # create and delete a temporary file in the theme dir. install(CODE " @@ -192,6 +208,10 @@ function(_ecm_update_iconcache installdir theme) if (NOT DESTDIR_VALUE) file(WRITE \"${installdir}/${theme}/temp.txt\" \"update\") file(REMOVE \"${installdir}/${theme}/temp.txt\") + set(HAVE_GTK_UPDATE_ICON_CACHE_EXEC ${GTK_UPDATE_ICON_CACHE_EXECUTABLE}) + if (HAVE_GTK_UPDATE_ICON_CACHE_EXEC) + execute_process(COMMAND ${GTK_UPDATE_ICON_CACHE_EXECUTABLE} -q -t -i . WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}/${installdir}/${theme}\") + endif () endif (NOT DESTDIR_VALUE) ") endfunction() @@ -221,8 +241,9 @@ function(ecm_install_icons) endif() foreach(icon ${ARG_ICONS}) + get_filename_component(filename "${icon}" NAME) string(REGEX MATCH "([0-9sc]+)\\-([a-z]+)\\-([^/]+)\\.([a-z]+)$" - _dummy "${icon}") + complete_match "${filename}") set(size "${CMAKE_MATCH_1}") set(group "${CMAKE_MATCH_2}") set(name "${CMAKE_MATCH_3}") @@ -232,6 +253,12 @@ function(ecm_install_icons) elseif(NOT size STREQUAL "sc" AND NOT size GREATER 0) message(WARNING "${icon} size (${size}) is invalid - ignoring") else() + if (NOT complete_match STREQUAL filename) + # We can't stop accepting filenames with leading characters, + # because that would break existing projects, so just warn + # about them instead. + message(AUTHOR_WARNING "\"${icon}\" has characters before the size; it should be renamed to \"${size}-${group}-${name}.${ext}\"") + endif() if(NOT _ECM_ICON_GROUP_${group}) message(WARNING "${icon} group (${group}) is not recognized") endif() diff --git a/modules/ECMMarkAsTest.cmake b/modules/ECMMarkAsTest.cmake index 24b8cfc7..9027bf30 100644 --- a/modules/ECMMarkAsTest.cmake +++ b/modules/ECMMarkAsTest.cmake @@ -13,6 +13,8 @@ # # BUILD_TESTING is created as a cache variable by the CTest module and by the # :kde-module:`KDECMakeSettings` module. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2012 Stephen Kelly <steveire@gmail.com> diff --git a/modules/ECMMarkNonGuiExecutable.cmake b/modules/ECMMarkNonGuiExecutable.cmake index 9b680216..59737d4c 100644 --- a/modules/ECMMarkNonGuiExecutable.cmake +++ b/modules/ECMMarkNonGuiExecutable.cmake @@ -11,6 +11,8 @@ # This will indicate to CMake that the specified targets should not be included # in a MACOSX_BUNDLE and should not be WIN32_EXECUTABLEs. On platforms other # than MacOS X or Windows, this will have no effect. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2012 Stephen Kelly <steveire@gmail.com> diff --git a/modules/ECMOptionalAddSubdirectory.cmake b/modules/ECMOptionalAddSubdirectory.cmake index 6cbafa2d..2b890055 100644 --- a/modules/ECMOptionalAddSubdirectory.cmake +++ b/modules/ECMOptionalAddSubdirectory.cmake @@ -24,6 +24,8 @@ # .. code-block:: sh # # cmake -DDISABLE_ALL_OPTIONAL_SUBDIRECTORIES=TRUE -DBUILD_foo=TRUE myproject +# +# Since pre-1.0.0. #============================================================================= # Copyright 2007 Alexander Neundorf <neundorf@kde.org> diff --git a/modules/ECMPackageConfigHelpers.cmake b/modules/ECMPackageConfigHelpers.cmake index bc99d1cb..d1d0408f 100644 --- a/modules/ECMPackageConfigHelpers.cmake +++ b/modules/ECMPackageConfigHelpers.cmake @@ -5,7 +5,9 @@ # Helper macros for generating CMake package config files. # # ``write_basic_package_version_file()`` is the same as the one provided by the -# CMakePackageConfigHelpers module in CMake; see that module's documentation for +# `CMakePackageConfigHelpers +# <http://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:CMakePackageConfigHelpers>`_ +# module in CMake; see that module's documentation for # more information. # # :: @@ -18,7 +20,23 @@ # # # This behaves in the same way as configure_package_config_file() from CMake -# 2.8.12, except that it adds an extra helper macro: find_dependency(). +# 2.8.12, except that it adds an extra helper macro: find_dependency(). It is +# highly recommended that you read the `documentation for +# CMakePackageConfigHelpers +# <http://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:CMakePackageConfigHelpers>`_ +# for more information, particularly with regard to the PATH_VARS argument. +# +# Note that there is no argument that will disable the find_dependency() macro; +# if you do not require this macro, you should use +# ``configure_package_config_file`` from the CMakePackageConfigHelpers module. +# +# CMake 3.0 includes a CMakeFindDependencyMacro module that provides the +# find_dependency() macro (which you can ``include()`` in your package config +# file), so this file is only useful for projects wishing to provide config +# files that will work with CMake 2.8.12. +# +# Additional Config File Macros +# ============================= # # :: # @@ -29,14 +47,7 @@ # REQUIRED which were passed to the original find_package() call. It also sets # an informative diagnostic message if the dependency could not be found. # -# Note that there is no argument to disable the find_dependency() macro; if you -# do not require this macro, you should just use the CMakeFindDependencyMacro -# module directly. -# -# CMake 3.0.0 will include a CMakeFindDependencyMacro module that will provide -# the find_dependency() macro (which you can include() in your package config -# file), so this file is only useful for projects whose minimum required version -# is 2.8.12. +# Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kdemail.net> diff --git a/modules/ECMPoQmTools.cmake b/modules/ECMPoQmTools.cmake index 74dc6563..12bcf6b6 100644 --- a/modules/ECMPoQmTools.cmake +++ b/modules/ECMPoQmTools.cmake @@ -65,6 +65,8 @@ # ``<install_destination>`` defaults to ``${LOCALE_INSTALL_DIR}`` if defined, # otherwise it uses ``${CMAKE_INSTALL_LOCALEDIR}`` if that is defined, otherwise # it uses ``share/locale``. +# +# Since pre-1.0.0. #============================================================================= # Copyright 2007-2009 Kitware, Inc. @@ -119,18 +121,20 @@ function(ecm_process_po_files_as_qm lang) endif() # Find lrelease and lconvert - - # This gives us Qt5::lrelease but unfortunately no Qt5::lconvert See - # https://bugreports.qt-project.org/browse/QTBUG-37937 find_package(Qt5LinguistTools CONFIG REQUIRED) - get_target_property(lrelease_location Qt5::lrelease LOCATION) - get_filename_component(lrelease_path ${lrelease_location} PATH) - find_program(lconvert_executable - NAMES lconvert-qt5 lconvert - PATHS ${lrelease_path} - NO_DEFAULT_PATH - ) + if(TARGET Qt5::lconvert) + set(lconvert_executable Qt5::lconvert) + else() + # Qt < 5.3.1 does not define Qt5::lconvert + get_target_property(lrelease_location Qt5::lrelease LOCATION) + get_filename_component(lrelease_path ${lrelease_location} PATH) + find_program(lconvert_executable + NAMES lconvert-qt5 lconvert + PATHS ${lrelease_path} + NO_DEFAULT_PATH + ) + endif() # Create commands to turn po files into qm files set(qm_files) @@ -151,7 +155,7 @@ function(ecm_process_po_files_as_qm lang) COMMAND ${lconvert_executable} ARGS -i ${po_file} -o ${ts_file} -target-language ${lang} COMMAND Qt5::lrelease - ARGS -compress -removeidentical -silent ${ts_file} -qm ${qm_file} + ARGS -removeidentical -silent ${ts_file} -qm ${qm_file} DEPENDS ${po_file} ) if (ARGS_INSTALL_DESTINATION) diff --git a/modules/ECMQmLoader.cpp.in b/modules/ECMQmLoader.cpp.in index bc01bf98..423d1c93 100644 --- a/modules/ECMQmLoader.cpp.in +++ b/modules/ECMQmLoader.cpp.in @@ -2,6 +2,33 @@ * * Building this file in a library ensures translations are automatically loaded * when an application makes use of the library. + * + * + * Copyright 2014 Aurélien Gâteau <agateau@kde.org> + * Copyright 2015 Alex Merry <alex.merry@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 <QCoreApplication> #include <QLocale> diff --git a/modules/ECMQtDeclareLoggingCategory.cmake b/modules/ECMQtDeclareLoggingCategory.cmake new file mode 100644 index 00000000..b7f1ad39 --- /dev/null +++ b/modules/ECMQtDeclareLoggingCategory.cmake @@ -0,0 +1,118 @@ +#.rst: +# ECMQtDeclareLoggingCategory +# --------------------------- +# +# Generate declarations for logging categories in Qt5. +# +# :: +# +# ecm_qt_declare_logging_category(<sources_var> +# HEADER <filename> +# IDENTIFIER <identifier> +# CATEGORY_NAME <category_name> +# [DEFAULT_SEVERITY +# <Debug|Info|Warning| +# Critical|Fatal>]) +# +# A header file, ``<filename>``, will be generated along with a corresponding +# source file, which will be added to ``<sources_var>``. These will provide a +# QLoggingCategory category that can be referred to from C++ code using +# ``<identifier>``, and from the logging configuration using +# ``<category_name>``. +# +# If ``<filename>`` is not absolute, it will be taken relative to the current +# binary directory. +# +# If the code is compiled against Qt 5.4 or later, by default it will only log +# output that is at least the severity specified by ``DEFAULT_SEVERITY``, or +# "Warning" level if ``DEFAULT_SEVERITY`` is not given. Note that, due to a +# bug in Qt 5.5, "Info" may be treated as more severe than "Fatal". +# +# ``<identifier>`` may include namespaces (eg: ``foo::bar::IDENT``). +# +# Since 5.14.0. + +#============================================================================= +# Copyright 2015 Alex Merry <alex.merry@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +# License text for the above reference.) + +include(CMakeParseArguments) + +set(_ECM_QT_DECLARE_LOGGING_CATEGORY_TEMPLATE_CPP "${CMAKE_CURRENT_LIST_DIR}/ECMQtDeclareLoggingCategory.cpp.in") +set(_ECM_QT_DECLARE_LOGGING_CATEGORY_TEMPLATE_H "${CMAKE_CURRENT_LIST_DIR}/ECMQtDeclareLoggingCategory.h.in") + +function(ecm_qt_declare_logging_category sources_var) + set(options) + set(oneValueArgs HEADER IDENTIFIER CATEGORY_NAME DEFAULT_SEVERITY) + set(multiValueArgs) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(ARG_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unexpected arguments to ecm_qt_declare_logging_category: ${ARG_UNPARSED_ARGUMENTS}") + endif() + if(NOT ARG_HEADER) + message(FATAL_ERROR "Missing HEADER argument for ecm_qt_declare_logging_category") + endif() + if(NOT ARG_IDENTIFIER) + message(FATAL_ERROR "Missing IDENTIFIER argument for ecm_qt_declare_logging_category") + endif() + if(NOT ARG_CATEGORY_NAME) + message(FATAL_ERROR "Missing CATEGORY_NAME argument for ecm_qt_declare_logging_category") + endif() + if(NOT ARG_DEFAULT_SEVERITY) + set(ARG_DEFAULT_SEVERITY Warning) + else() + set(acceptible_severities Debug Info Warning Critical Fatal) + list(FIND acceptible_severities "${ARG_DEFAULT_SEVERITY}" pos) + if (pos EQUAL -1) + message(FATAL_ERROR "Unknown DEFAULT_SEVERITY ${pos}") + endif() + endif() + + if (NOT IS_ABSOLUTE "${ARG_HEADER}") + set(ARG_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${ARG_HEADER}") + endif() + + string(REPLACE "::" ";" namespaces "${ARG_IDENTIFIER}") + list(LENGTH namespaces len) + math(EXPR last_pos "${len} - 1") + list(GET namespaces ${last_pos} IDENTIFIER) + list(REMOVE_AT namespaces ${last_pos}) + + set(OPEN_NAMESPACES) + set(CLOSE_NAMESPACES) + foreach(ns ${namespaces}) + set(OPEN_NAMESPACES "${OPEN_NAMESPACES} namespace ${ns} {") + set(CLOSE_NAMESPACES "} ${CLOSE_NAMESPACES}") + endforeach() + + string(FIND "${ARG_HEADER}" "." pos REVERSE) + if (pos EQUAL -1) + set(cpp_filename "${ARG_HEADER}.cpp") + else() + string(SUBSTRING "${ARG_HEADER}" 0 ${pos} cpp_filename) + set(cpp_filename "${cpp_filename}.cpp") + endif() + + get_filename_component(HEADER_NAME "${ARG_HEADER}" NAME) + + string(REPLACE "::" "_" GUARD_NAME "${ARG_IDENTIFIER}_H") + string(TOUPPER "${GUARD_NAME}" GUARD_NAME) + + configure_file("${_ECM_QT_DECLARE_LOGGING_CATEGORY_TEMPLATE_CPP}" "${cpp_filename}") + configure_file("${_ECM_QT_DECLARE_LOGGING_CATEGORY_TEMPLATE_H}" "${ARG_HEADER}") + + set(sources "${${sources_var}}") + list(APPEND sources "${cpp_filename}") + set(${sources_var} "${sources}" PARENT_SCOPE) +endfunction() + diff --git a/modules/ECMQtDeclareLoggingCategory.cpp.in b/modules/ECMQtDeclareLoggingCategory.cpp.in new file mode 100644 index 00000000..20c14af5 --- /dev/null +++ b/modules/ECMQtDeclareLoggingCategory.cpp.in @@ -0,0 +1,11 @@ +// This file is autogenerated by CMake: DO NOT EDIT + +#include "@HEADER_NAME@" + +@OPEN_NAMESPACES@ +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) +Q_LOGGING_CATEGORY(@IDENTIFIER@, "@ARG_CATEGORY_NAME@", Qt@ARG_DEFAULT_SEVERITY@Msg) +#else +Q_LOGGING_CATEGORY(@IDENTIFIER@, "@ARG_CATEGORY_NAME@") +#endif +@CLOSE_NAMESPACES@ diff --git a/modules/ECMQtDeclareLoggingCategory.h.in b/modules/ECMQtDeclareLoggingCategory.h.in new file mode 100644 index 00000000..fedecd2f --- /dev/null +++ b/modules/ECMQtDeclareLoggingCategory.h.in @@ -0,0 +1,11 @@ +// This file is autogenerated by CMake: DO NOT EDIT + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <QLoggingCategory> +@OPEN_NAMESPACES@ +Q_DECLARE_LOGGING_CATEGORY(@IDENTIFIER@) +@CLOSE_NAMESPACES@ + +#endif diff --git a/modules/ECMQueryQmake.cmake b/modules/ECMQueryQmake.cmake index c880671f..8f4cf177 100644 --- a/modules/ECMQueryQmake.cmake +++ b/modules/ECMQueryQmake.cmake @@ -19,6 +19,7 @@ function(query_qmake result_variable qt_variable) file(TO_CMAKE_PATH "${output}" output_path) set(${result_variable} "${output_path}" PARENT_SCOPE) else() - message(FATAL "QMake call failed: ${error}") + message(WARNING "Failed call: ${QMAKE_EXECUTABLE} -query \"${qt_variable}\"") + message(FATAL_ERROR "QMake call failed: ${return_code}") endif() endfunction() diff --git a/modules/ECMSetupVersion.cmake b/modules/ECMSetupVersion.cmake index b908f96e..33d0ada1 100644 --- a/modules/ECMSetupVersion.cmake +++ b/modules/ECMSetupVersion.cmake @@ -73,6 +73,9 @@ # first argument. In all other respects, it behaves like the other form of the # command. # +# Since pre-1.0.0. +# +# COMPATIBLITY option available since 1.6.0. #============================================================================= # Copyright 2014 Alex Merry <alex.merry@kde.org> diff --git a/modules/ECMUninstallTarget.cmake b/modules/ECMUninstallTarget.cmake new file mode 100644 index 00000000..1e9bb91e --- /dev/null +++ b/modules/ECMUninstallTarget.cmake @@ -0,0 +1,58 @@ +#.rst: +# ECMUninstallTarget +# ------------------ +# +# Add an ``uninstall`` target. +# +# By including this module, an ``uninstall`` target will be added to your CMake +# project. This will remove all files installed (or updated) by a previous +# invocation of the ``install`` target. It will not remove files created or +# modified by an ``install(SCRIPT)`` or ``install(CODE)`` command; you should +# create a custom uninstallation target for these and use ``add_dependency`` to +# make the ``uninstall`` target depend on it: +# +# .. code-block:: cmake +# +# include(ECMUninstallTarget) +# install(SCRIPT install-foo.cmake) +# add_custom_target(uninstall_foo COMMAND ${CMAKE_COMMAND} -P uninstall-foo.cmake) +# add_dependency(uninstall uninstall_foo) +# +# The target will fail if the ``install`` target has not yet been run (so it is +# not possible to run CMake on the project and then immediately run the +# ``uninstall`` target). +# +# .. warning:: +# +# CMake deliberately does not provide an ``uninstall`` target by default on +# the basis that such a target has the potential to remove important files +# from a user's computer. Use with caution. +# +# Since 1.7.0. + +#============================================================================= +# Copyright 2015 Alex Merry <alex.merry@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +# License text for the above reference.) + +if (NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_LIST_DIR}/ecm_uninstall.cmake.in" + "${CMAKE_BINARY_DIR}/ecm_uninstall.cmake" + IMMEDIATE + @ONLY + ) + + add_custom_target(uninstall + COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_BINARY_DIR}/ecm_uninstall.cmake" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + ) +endif() diff --git a/modules/ECMUseFindModules.cmake b/modules/ECMUseFindModules.cmake index a48f599b..0a8a40fb 100644 --- a/modules/ECMUseFindModules.cmake +++ b/modules/ECMUseFindModules.cmake @@ -44,6 +44,8 @@ # be installed along with config files if they are required as a dependency (for # example, if targets provided by the find module are in the link interface of a # library). +# +# Since pre-1.0.0. #============================================================================= # Copyright 2011 Alexander Neundorf <neundorf@kde.org> diff --git a/modules/ecm_uninstall.cmake.in b/modules/ecm_uninstall.cmake.in new file mode 100644 index 00000000..379239ba --- /dev/null +++ b/modules/ecm_uninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") +endif() + +file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif() + else() + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif() +endforeach() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bc3e5ce8..9e6de12f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,6 +4,7 @@ # with other files (as ECM itself is architecture-independent). project(ECMTests C) +add_subdirectory(ECMAddTests) add_subdirectory(ECMGenerateHeadersTest) add_subdirectory(ECMSetupVersionTest) add_subdirectory(ECMGeneratePkgConfigFile) @@ -84,6 +85,9 @@ if (TARGET Qt5::qmake) add_test_variant(KDEInstallDirsTest.relative_or_absolute_qt KDEInstallDirsTest.relative_or_absolute dummy) endif () +if (Qt5Core_FOUND) + add_test_macro(ECMQtDeclareLoggingCategoryTest testmain) +endif() add_test_macro(FindModules dummy) add_test_macro(UseFindModules dummy) @@ -97,13 +101,13 @@ add_test_macro(ECMInstallIconsTest ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/ECMInstallIconsTest/check_tree.cmake" ) -if (Qt5LinguistTools_FOUND) +if (Qt5Core_FOUND AND Qt5LinguistTools_FOUND) set(ECMPoQmToolsTest_EXTRA_OPTIONS --build-target install --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/ECMPoQmToolsTest/InstallDirectory" ) add_test_macro(ECMPoQmToolsTest - ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/ECMPoQmToolsTest/check_tree.cmake" + ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/ECMPoQmToolsTest/check.cmake" ) endif() diff --git a/tests/ECMAddTests/CMakeLists.txt b/tests/ECMAddTests/CMakeLists.txt new file mode 100644 index 00000000..e77b33f9 --- /dev/null +++ b/tests/ECMAddTests/CMakeLists.txt @@ -0,0 +1,49 @@ +macro(add_check NAME) + string(REPLACE "." "/" dir "${NAME}") + string(REGEX REPLACE "[^.]*\\." "" proj "${NAME}") + add_test( + NAME ecm_add_tests-${NAME} + COMMAND + ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMAKE_CURRENT_SOURCE_DIR}/${dir}" + "${CMAKE_CURRENT_BINARY_DIR}/${dir}" + --build-two-config + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-project ${proj} + --build-options -DBUILD_TESTING:BOOL=ON + ${${NAME}_EXTRA_OPTIONS} + --test-command "${CMAKE_CTEST_COMMAND}" + ) + add_test( + NAME ecm_add_tests_did_run-${NAME} + COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/check_files.cmake" ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${dir}" + ) + set_property(TEST ecm_add_tests_did_run-${NAME} + APPEND + PROPERTY DEPENDS "ecm_add_tests-${NAME}" + ) +endmacro() + +add_check(single_tests + test1.txt + test2.txt + test3.txt + test4.txt + test5.txt + test6.txt + ) +add_check(multi_tests + test1.txt + test2.txt + test3.txt + test4.txt + test5.txt + test6.txt + test7.txt + test8.txt + test9.txt + ) + diff --git a/tests/ECMAddTests/check_files.cmake b/tests/ECMAddTests/check_files.cmake new file mode 100644 index 00000000..fc6003c6 --- /dev/null +++ b/tests/ECMAddTests/check_files.cmake @@ -0,0 +1,15 @@ +set(i 0) +set(in_file_args FALSE) +while (i LESS CMAKE_ARGC) + if (in_file_args) + if (NOT EXISTS "${CMAKE_ARGV${i}}") + message(FATAL_ERROR "${CMAKE_ARGV${i}} does not exist") + endif() + elseif (CMAKE_ARGV${i} STREQUAL "-P") + # skip script name + math(EXPR i "${i} + 1") + set(in_file_args TRUE) + endif() + math(EXPR i "${i} + 1") +endwhile() + diff --git a/tests/ECMAddTests/multi_tests/CMakeLists.txt b/tests/ECMAddTests/multi_tests/CMakeLists.txt new file mode 100644 index 00000000..0133c7d6 --- /dev/null +++ b/tests/ECMAddTests/multi_tests/CMakeLists.txt @@ -0,0 +1,155 @@ +project(ECMAddTests) +cmake_minimum_required(VERSION 2.8.12) + +set(ECM_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../modules) +set(CMAKE_MODULE_PATH "${ECM_MODULE_DIR}") + +add_library(testhelper STATIC ../testhelper.cpp) +target_include_directories(testhelper PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") + +enable_testing() + +include(ECMAddTests) +include(../../test_helpers.cmake) + +# clean up to avoid false-positives from check_files.cmake +file(REMOVE + "${CMAKE_CURRENT_BINARY_DIR}/test1.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test2.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test3.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test4.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test5.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test6.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test7.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test8.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test9.txt" + ) + +set(exp_target_names "test1;test2;test3") +set(exp_test_names "test1;test2;test3") +ecm_add_tests( + test1.cpp + test2.cpp + test3.cpp + LINK_LIBRARIES testhelper + TARGET_NAMES_VAR target_names + TEST_NAMES_VAR test_names + ) +assert_vars_setequal(target_names exp_target_names) +assert_vars_setequal(test_names exp_test_names) +# check targets exist +get_property(_dummy TARGET test1 PROPERTY TYPE) +get_property(_dummy TARGET test2 PROPERTY TYPE) +get_property(_dummy TARGET test3 PROPERTY TYPE) +# check tests exists +get_property(_dummy TEST test1 PROPERTY TIMEOUT) +get_property(_dummy TEST test2 PROPERTY TIMEOUT) +get_property(_dummy TEST test3 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test1 PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "test1 is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET test1 PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "test1 is an OS/X bundle when it should not be") +endif() +get_property(_is_win32 TARGET test2 PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "test2 is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET test2 PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "test2 is an OS/X bundle when it should not be") +endif() + + +ecm_add_tests( + test4.cpp + test5.cpp + LINK_LIBRARIES testhelper + NAME_PREFIX pref_ + ) +get_property(_dummy TARGET test4 PROPERTY TYPE) +get_property(_dummy TARGET test5 PROPERTY TYPE) +get_property(_dummy TEST pref_test4 PROPERTY TIMEOUT) +get_property(_dummy TEST pref_test5 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test4 PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "test4 is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET test4 PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "test4 is an OS/X bundle when it should not be") +endif() +get_property(_is_win32 TARGET test5 PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "test5 is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET test5 PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "test5 is an OS/X bundle when it should not be") +endif() + + +ecm_add_tests( + test6.cpp + test7.cpp + LINK_LIBRARIES testhelper + GUI + ) +get_property(_dummy TARGET test6 PROPERTY TYPE) +get_property(_dummy TARGET test7 PROPERTY TYPE) +get_property(_dummy TEST test6 PROPERTY TIMEOUT) +get_property(_dummy TEST test7 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test6 PROPERTY WIN32_EXECUTABLE) +if (NOT _is_win32) + message(FATAL_ERROR "test6 is not a WIN32 executable when it should be") +endif() +get_property(_is_bundle TARGET test6 PROPERTY MACOSX_BUNDLE) +if (NOT _is_bundle) + message(FATAL_ERROR "test6 is not an OS/X bundle when it should be") +endif() +get_property(_is_win32 TARGET test7 PROPERTY WIN32_EXECUTABLE) +if (NOT _is_win32) + message(FATAL_ERROR "test7 is not a WIN32 executable when it should be") +endif() +get_property(_is_bundle TARGET test7 PROPERTY MACOSX_BUNDLE) +if (NOT _is_bundle) + message(FATAL_ERROR "test7 is not an OS/X bundle when it should be") +endif() + + +set(exp_target_names "test8;test9") +set(exp_test_names "p_test8;p_test9") +ecm_add_tests( + test8.cpp + test9.cpp + LINK_LIBRARIES testhelper + NAME_PREFIX p_ + GUI + TARGET_NAMES_VAR target_names + TEST_NAMES_VAR test_names + ) +assert_vars_setequal(target_names exp_target_names) +assert_vars_setequal(test_names exp_test_names) +get_property(_dummy TARGET test8 PROPERTY TYPE) +get_property(_dummy TARGET test9 PROPERTY TYPE) +get_property(_dummy TEST p_test8 PROPERTY TIMEOUT) +get_property(_dummy TEST p_test9 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test8 PROPERTY WIN32_EXECUTABLE) +if (NOT _is_win32) + message(FATAL_ERROR "test8 is not a WIN32 executable when it should be") +endif() +get_property(_is_bundle TARGET test8 PROPERTY MACOSX_BUNDLE) +if (NOT _is_bundle) + message(FATAL_ERROR "test8 is not an OS/X bundle when it should be") +endif() +get_property(_is_win32 TARGET test9 PROPERTY WIN32_EXECUTABLE) +if (NOT _is_win32) + message(FATAL_ERROR "test9 is not a WIN32 executable when it should be") +endif() +get_property(_is_bundle TARGET test9 PROPERTY MACOSX_BUNDLE) +if (NOT _is_bundle) + message(FATAL_ERROR "test9 is not an OS/X bundle when it should be") +endif() + diff --git a/tests/ECMAddTests/multi_tests/test1.cpp b/tests/ECMAddTests/multi_tests/test1.cpp new file mode 100644 index 00000000..e5482865 --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test1.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test1.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test2.cpp b/tests/ECMAddTests/multi_tests/test2.cpp new file mode 100644 index 00000000..7f45bb56 --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test2.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test2.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test3.cpp b/tests/ECMAddTests/multi_tests/test3.cpp new file mode 100644 index 00000000..142b2765 --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test3.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test3.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test4.cpp b/tests/ECMAddTests/multi_tests/test4.cpp new file mode 100644 index 00000000..1ba9b148 --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test4.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test4.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test5.cpp b/tests/ECMAddTests/multi_tests/test5.cpp new file mode 100644 index 00000000..987af36b --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test5.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test5.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test6.cpp b/tests/ECMAddTests/multi_tests/test6.cpp new file mode 100644 index 00000000..6bda9f0d --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test6.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test6.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test7.cpp b/tests/ECMAddTests/multi_tests/test7.cpp new file mode 100644 index 00000000..069859e7 --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test7.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test7.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test8.cpp b/tests/ECMAddTests/multi_tests/test8.cpp new file mode 100644 index 00000000..ce762c8d --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test8.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test8.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/multi_tests/test9.cpp b/tests/ECMAddTests/multi_tests/test9.cpp new file mode 100644 index 00000000..e432aeba --- /dev/null +++ b/tests/ECMAddTests/multi_tests/test9.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test9.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/CMakeLists.txt b/tests/ECMAddTests/single_tests/CMakeLists.txt new file mode 100644 index 00000000..6af3857b --- /dev/null +++ b/tests/ECMAddTests/single_tests/CMakeLists.txt @@ -0,0 +1,122 @@ +project(ECMAddTests) +cmake_minimum_required(VERSION 2.8.12) + +set(ECM_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../modules) +set(CMAKE_MODULE_PATH "${ECM_MODULE_DIR}") + +add_library(testhelper STATIC ../testhelper.cpp) +target_include_directories(testhelper PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") + +enable_testing() + +include(ECMAddTests) + +# clean up to avoid false-positives from check_files.cmake +file(REMOVE + "${CMAKE_CURRENT_BINARY_DIR}/test1.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test2.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test3.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test4.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test5.txt" + "${CMAKE_CURRENT_BINARY_DIR}/test6.txt" + ) + +ecm_add_test(test1.cpp + LINK_LIBRARIES testhelper + ) +# check target exists +get_property(_dummy TARGET test1 PROPERTY TYPE) +# check test exists +get_property(_dummy TEST test1 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test1 PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "test1 is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET test1 PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "test1 is an OS/X bundle when it should not be") +endif() + + +ecm_add_test(test2.cpp + LINK_LIBRARIES testhelper + TEST_NAME named_test + ) +get_property(_dummy TARGET named_test PROPERTY TYPE) +get_property(_dummy TEST named_test PROPERTY TIMEOUT) +get_property(_is_win32 TARGET named_test PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "named_test is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET named_test PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "named_test is an OS/X bundle when it should not be") +endif() + + +ecm_add_test(test3.cpp + LINK_LIBRARIES testhelper + NAME_PREFIX prefix_ + ) +get_property(_dummy TARGET test3 PROPERTY TYPE) +get_property(_dummy TEST prefix_test3 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test3 PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "test3 is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET test3 PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "test3 is an OS/X bundle when it should not be") +endif() + + +ecm_add_test(test4.cpp + LINK_LIBRARIES testhelper + GUI + ) +get_property(_dummy TARGET test4 PROPERTY TYPE) +get_property(_dummy TEST test4 PROPERTY TIMEOUT) +get_property(_is_win32 TARGET test4 PROPERTY WIN32_EXECUTABLE) +if (NOT _is_win32) + message(FATAL_ERROR "test4 is not a WIN32 executable when it should be") +endif() +get_property(_is_bundle TARGET test4 PROPERTY MACOSX_BUNDLE) +if (NOT _is_bundle) + message(FATAL_ERROR "test4 is not an OS/X bundle when it should be") +endif() + + +ecm_add_test(test5.cpp + LINK_LIBRARIES testhelper + TEST_NAME combined_test + NAME_PREFIX another_prefix_ + GUI + ) +get_property(_dummy TARGET combined_test PROPERTY TYPE) +get_property(_dummy TEST another_prefix_combined_test PROPERTY TIMEOUT) +get_property(_is_win32 TARGET combined_test PROPERTY WIN32_EXECUTABLE) +if (NOT _is_win32) + message(FATAL_ERROR "combined_test is not a WIN32 executable when it should be") +endif() +get_property(_is_bundle TARGET combined_test PROPERTY MACOSX_BUNDLE) +if (NOT _is_bundle) + message(FATAL_ERROR "combined_test is not an OS/X bundle when it should be") +endif() + + +ecm_add_test(test6.cpp test6body.cpp + LINK_LIBRARIES testhelper + TEST_NAME multifile_test + ) +get_property(_dummy TARGET multifile_test PROPERTY TYPE) +get_property(_dummy TEST multifile_test PROPERTY TIMEOUT) +get_property(_is_win32 TARGET multifile_test PROPERTY WIN32_EXECUTABLE) +if (_is_win32) + message(FATAL_ERROR "multifile_test is a WIN32 executable when it should not be") +endif() +get_property(_is_bundle TARGET multifile_test PROPERTY MACOSX_BUNDLE) +if (_is_bundle) + message(FATAL_ERROR "multifile_test is an OS/X bundle when it should not be") +endif() + + diff --git a/tests/ECMAddTests/single_tests/test1.cpp b/tests/ECMAddTests/single_tests/test1.cpp new file mode 100644 index 00000000..e5482865 --- /dev/null +++ b/tests/ECMAddTests/single_tests/test1.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test1.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/test2.cpp b/tests/ECMAddTests/single_tests/test2.cpp new file mode 100644 index 00000000..7f45bb56 --- /dev/null +++ b/tests/ECMAddTests/single_tests/test2.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test2.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/test3.cpp b/tests/ECMAddTests/single_tests/test3.cpp new file mode 100644 index 00000000..142b2765 --- /dev/null +++ b/tests/ECMAddTests/single_tests/test3.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test3.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/test4.cpp b/tests/ECMAddTests/single_tests/test4.cpp new file mode 100644 index 00000000..1ba9b148 --- /dev/null +++ b/tests/ECMAddTests/single_tests/test4.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test4.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/test5.cpp b/tests/ECMAddTests/single_tests/test5.cpp new file mode 100644 index 00000000..987af36b --- /dev/null +++ b/tests/ECMAddTests/single_tests/test5.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" + +int main() +{ + make_test_file("test5.txt"); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/test6.cpp b/tests/ECMAddTests/single_tests/test6.cpp new file mode 100644 index 00000000..33cd0421 --- /dev/null +++ b/tests/ECMAddTests/single_tests/test6.cpp @@ -0,0 +1,8 @@ +void test_body(); + +int main() +{ + test_body(); + return 0; +} + diff --git a/tests/ECMAddTests/single_tests/test6body.cpp b/tests/ECMAddTests/single_tests/test6body.cpp new file mode 100644 index 00000000..c3332738 --- /dev/null +++ b/tests/ECMAddTests/single_tests/test6body.cpp @@ -0,0 +1,7 @@ +#include "testhelper.h" + +void test_body() +{ + make_test_file("test6.txt"); +} + diff --git a/tests/ECMAddTests/testhelper.cpp b/tests/ECMAddTests/testhelper.cpp new file mode 100644 index 00000000..00d0ceed --- /dev/null +++ b/tests/ECMAddTests/testhelper.cpp @@ -0,0 +1,8 @@ +#include "testhelper.h" +#include <fstream> +#include <string> + +void make_test_file(const char *filename) +{ + std::ofstream(filename) << "test" << std::endl; +} diff --git a/tests/ECMAddTests/testhelper.h b/tests/ECMAddTests/testhelper.h new file mode 100644 index 00000000..9810ee41 --- /dev/null +++ b/tests/ECMAddTests/testhelper.h @@ -0,0 +1 @@ +void make_test_file(const char *filename); diff --git a/tests/ECMGenerateHeadersTest/CamelCaseHeadTest1.h b/tests/ECMGenerateHeadersTest/CamelCaseHeadTest1.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/ECMGenerateHeadersTest/CamelCaseHeadTest1.h diff --git a/tests/ECMGenerateHeadersTest/CamelCaseHeadTest2.h b/tests/ECMGenerateHeadersTest/CamelCaseHeadTest2.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/ECMGenerateHeadersTest/CamelCaseHeadTest2.h diff --git a/tests/ECMGenerateHeadersTest/CommonHeader b/tests/ECMGenerateHeadersTest/CommonHeader new file mode 100644 index 00000000..0d101fbc --- /dev/null +++ b/tests/ECMGenerateHeadersTest/CommonHeader @@ -0,0 +1,4 @@ +// convenience header +#include "headtest1.h" +#include "headtest2.h" +#include "headtest4.h" diff --git a/tests/ECMGenerateHeadersTest/headtest4.h b/tests/ECMGenerateHeadersTest/headtest4.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/ECMGenerateHeadersTest/headtest4.h diff --git a/tests/ECMGenerateHeadersTest/run_test.cmake.config b/tests/ECMGenerateHeadersTest/run_test.cmake.config index 0a2425fe..a9027dbc 100644 --- a/tests/ECMGenerateHeadersTest/run_test.cmake.config +++ b/tests/ECMGenerateHeadersTest/run_test.cmake.config @@ -244,4 +244,114 @@ check_files(GENERATED ${expfiles} ORIGINALS ${origfiles}) +########################################################### + +message(STATUS "Test 10: ORIGINAL CAMELCASE") +set(forward_headers) +set(expfiles "${CMAKE_CURRENT_BINARY_DIR}/CamelCaseHeadTest1" + "${CMAKE_CURRENT_BINARY_DIR}/CamelCaseHeadTest2") +set(origfiles CamelCaseHeadTest1.h CamelCaseHeadTest2.h) +file(REMOVE ${expfiles}) +ecm_generate_headers( + forward_headers + ORIGINAL CAMELCASE + HEADER_NAMES CamelCaseHeadTest1 CamelCaseHeadTest2 +) +if (NOT "${expfiles}" STREQUAL "${forward_headers}") + message(FATAL_ERROR "forward_headers was set to \"${forward_headers}\" instead of \"${expfiles}\"") +endif() +check_files(GENERATED ${expfiles} + ORIGINALS ${origfiles}) + + +########################################################### + +message(STATUS "Test 11: PREFIX and ORIGINAL CAMELCASE") +set(forward_headers) +set(expfiles "${CMAKE_CURRENT_BINARY_DIR}/Module/CamelCaseHeadTest1" + "${CMAKE_CURRENT_BINARY_DIR}/Module/CamelCaseHeadTest2") +set(intermediatefiles Module/CamelCaseHeadTest1.h Module/CamelCaseHeadTest2.h) +set(origfiles "${CMAKE_CURRENT_SOURCE_DIR}/headtest1.h" + "${CMAKE_CURRENT_SOURCE_DIR}/headtest2.h") +file(REMOVE ${expfiles} ${intermediatefiles}) +ecm_generate_headers( + forward_headers + ORIGINAL CAMELCASE + HEADER_NAMES CamelCaseHeadTest1 CamelCaseHeadTest2 + PREFIX Module +) +if (NOT "${expfiles}" STREQUAL "${forward_headers}") + message(FATAL_ERROR "forward_headers was set to \"${forward_headers}\" instead of \"${expfiles}\"") +endif() +check_files(GENERATED ${expfiles} + ORIGINALS ${intermediatefiles}) +check_files(GENERATED ${expfiles} + ORIGINALS ${intermediatefiles}) + +########################################################### + +message(STATUS "Test 12: COMMON_HEADER") + +set(camelcase_headers) +set(expfiles "${CMAKE_CURRENT_BINARY_DIR}/HeadTest1" + "${CMAKE_CURRENT_BINARY_DIR}/HeadTest2" + "${CMAKE_CURRENT_BINARY_DIR}/HeadTest4" + "${CMAKE_CURRENT_BINARY_DIR}/CommonHeader") +set(origfiles headtest1.h headtest2.h) +file(REMOVE ${expfiles}) +ecm_generate_headers( + camelcase_headers + ORIGINAL LOWERCASE + HEADER_NAMES HeadTest1 HeadTest2 HeadTest4 + COMMON_HEADER CommonHeader +) +if (NOT "${expfiles}" STREQUAL "${camelcase_headers}") + message(FATAL_ERROR "camelcase_headers was set to \"${camelcase_headers}\" instead of \"${expfiles}\"") +endif() +check_files(GENERATED ${expfiles} + ORIGINALS ${origfiles}) + +file(READ CommonHeader file_contents) +string(STRIP "${file_contents}" file_contents) +file(READ "${CMAKE_CURRENT_BINARY_DIR}/CommonHeader" exp_contents) +string(STRIP "${exp_contents}" exp_contents) +if (NOT "${file_contents}" STREQUAL "${exp_contents}") + message(FATAL_ERROR "${generated_file} contains '${file_contents}' instead of '${exp_contents}'") +endif() + + +########################################################### + +message(STATUS "Test 13: multiple classes and COMMON_HEADER") + +set(camelcase_headers) +set(expfiles "${CMAKE_CURRENT_BINARY_DIR}/HeadTest1" + "${CMAKE_CURRENT_BINARY_DIR}/HeadTest2" + "${CMAKE_CURRENT_BINARY_DIR}/HeadTest2Add1" + "${CMAKE_CURRENT_BINARY_DIR}/HeadTest2Add2" + "${CMAKE_CURRENT_BINARY_DIR}/HeadTest4" + "${CMAKE_CURRENT_BINARY_DIR}/CommonHeader") +set(origfiles headtest1.h headtest2.h headtest4.h) +file(REMOVE ${expfiles}) +ecm_generate_headers( + camelcase_headers + ORIGINAL LOWERCASE + HEADER_NAMES HeadTest1 HeadTest2,HeadTest2Add1,HeadTest2Add2 HeadTest4 + COMMON_HEADER CommonHeader +) +if (NOT "${expfiles}" STREQUAL "${camelcase_headers}") + message(FATAL_ERROR "camelcase_headers was set to \"${camelcase_headers}\" instead of \"${expfiles}\"") +endif() +check_files(GENERATED ${expfiles} + ORIGINALS ${origfiles}) + +file(READ CommonHeader file_contents) +string(STRIP "${file_contents}" file_contents) +file(READ "${CMAKE_CURRENT_BINARY_DIR}/CommonHeader" exp_contents) +string(STRIP "${exp_contents}" exp_contents) +if (NOT "${file_contents}" STREQUAL "${exp_contents}") + message(FATAL_ERROR "${generated_file} contains '${file_contents}' instead of '${exp_contents}'") +endif() + + # vim:ft=cmake diff --git a/tests/ECMGeneratePkgConfigFile/CMakeLists.txt b/tests/ECMGeneratePkgConfigFile/CMakeLists.txt index 9f407cb0..f3bc267d 100644 --- a/tests/ECMGeneratePkgConfigFile/CMakeLists.txt +++ b/tests/ECMGeneratePkgConfigFile/CMakeLists.txt @@ -2,5 +2,5 @@ set(MODULES_DIR "${extra-cmake-modules_SOURCE_DIR}/modules") configure_file(run_test.cmake.config "${CMAKE_CURRENT_BINARY_DIR}/run_test.cmake" @ONLY) add_test( - NAME ECMGenerateHeaders + NAME ECMGeneratePkgConfigFile COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/run_test.cmake") diff --git a/tests/ECMInstallIconsTest/CMakeLists.txt b/tests/ECMInstallIconsTest/CMakeLists.txt index 85f2d9f5..f048889e 100644 --- a/tests/ECMInstallIconsTest/CMakeLists.txt +++ b/tests/ECMInstallIconsTest/CMakeLists.txt @@ -10,6 +10,7 @@ include(ECMInstallIcons) add_subdirectory(v1-syntax) add_subdirectory(v1-syntax-l10n) +add_subdirectory(v1-syntax-no-icons) ecm_install_icons( ICONS 16-actions-computer.png @@ -20,7 +21,7 @@ ecm_install_icons( ICONS 16-actions-computer.png 16-animations-loading.mng - 16-apps-cmake.png + subdir/16-apps-cmake.png 16-categories-system-help.mng 16-emotes-face-smile.png 16-intl-something.png @@ -36,7 +37,7 @@ ecm_install_icons( ICONS 16-actions-computer.png 16-animations-loading.mng - 16-apps-cmake.png + subdir/16-apps-cmake.png 16-categories-system-help.mng 16-emotes-face-smile.png 16-intl-something.png @@ -53,7 +54,7 @@ ecm_install_icons( ICONS 16-actions-computer.png 16-animations-loading.mng - 16-apps-cmake.png + subdir/16-apps-cmake.png 16-categories-system-help.mng 16-emotes-face-smile.png 16-intl-something.png @@ -70,7 +71,7 @@ ecm_install_icons( ICONS 16-actions-computer.png 16-animations-loading.mng - 16-apps-cmake.png + subdir/16-apps-cmake.png 16-categories-system-help.mng 16-emotes-face-smile.png 16-intl-something.png @@ -87,11 +88,19 @@ ecm_install_icons( # all these should be warned about ecm_install_icons( ICONS - aa-actions-badsize.png # ignored - badlynamedfile.png # ignored - 16-actions-badext.txt # copied + aa-actions-badsize.png # ignored + badlynamedfile.png # ignored + 16-actions-badext.txt # copied + hi16-actions-old-style-name.png # copied DESTINATION badly-named-files-test ) +find_program(icon_cache_generator NAMES gtk-update-icon-cache) +if (icon_cache_generator) + set(GENERATE_ICON_CACHE TRUE) +else() + set(GENERATE_ICON_CACHE FALSE) +endif() + # this will be run by CTest configure_file(check_tree.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/check_tree.cmake" @ONLY) diff --git a/tests/ECMInstallIconsTest/check_tree.cmake.in b/tests/ECMInstallIconsTest/check_tree.cmake.in index 6d14246b..b9da1715 100644 --- a/tests/ECMInstallIconsTest/check_tree.cmake.in +++ b/tests/ECMInstallIconsTest/check_tree.cmake.in @@ -1,8 +1,15 @@ set(EXP_TREE "@CMAKE_CURRENT_SOURCE_DIR@/expected-tree") set(ACTUAL_TREE "@CMAKE_INSTALL_PREFIX@") +set(GENERATE_ICON_CACHE "@GENERATE_ICON_CACHE@") file(GLOB_RECURSE exp_files RELATIVE "${EXP_TREE}" "${EXP_TREE}/*") file(GLOB_RECURSE actual_files RELATIVE "${ACTUAL_TREE}" "${ACTUAL_TREE}/*") +if (NOT GENERATE_ICON_CACHE) + file(GLOB_RECURSE cache_files RELATIVE "${EXP_TREE}" "${EXP_TREE}/*.cache") + foreach(f ${cache_files}) + list(REMOVE_ITEM exp_files "${f}") + endforeach() +endif() list(SORT exp_files) list(SORT actual_files) diff --git a/tests/ECMInstallIconsTest/16-apps-cmake.png b/tests/ECMInstallIconsTest/expected-tree/badly-named-files-test/hicolor/16x16/actions/old-style-name.png Binary files differindex ed9a1181..ed9a1181 100644 --- a/tests/ECMInstallIconsTest/16-apps-cmake.png +++ b/tests/ECMInstallIconsTest/expected-tree/badly-named-files-test/hicolor/16x16/actions/old-style-name.png diff --git a/tests/ECMInstallIconsTest/expected-tree/badly-named-files-test/hicolor/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/badly-named-files-test/hicolor/icon-theme.cache Binary files differnew file mode 100644 index 00000000..50d52976 --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/badly-named-files-test/hicolor/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/lang-test/hicolor/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/lang-test/hicolor/icon-theme.cache Binary files differnew file mode 100644 index 00000000..babadff0 --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/lang-test/hicolor/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/multi-file-test/hicolor/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/multi-file-test/hicolor/icon-theme.cache Binary files differnew file mode 100644 index 00000000..60ac05d6 --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/multi-file-test/hicolor/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/single-file-test/hicolor/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/single-file-test/hicolor/icon-theme.cache Binary files differnew file mode 100644 index 00000000..f385659f --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/single-file-test/hicolor/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/themed-lang-test/oxygen/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/themed-lang-test/oxygen/icon-theme.cache Binary files differnew file mode 100644 index 00000000..babadff0 --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/themed-lang-test/oxygen/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/themed-test/theme-name-2/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/themed-test/theme-name-2/icon-theme.cache Binary files differnew file mode 100644 index 00000000..60ac05d6 --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/themed-test/theme-name-2/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/v1-icons/crystalsvg/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/v1-icons/crystalsvg/icon-theme.cache Binary files differnew file mode 100644 index 00000000..8b9c8d0c --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/v1-icons/crystalsvg/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/expected-tree/v1-icons/hicolor/icon-theme.cache b/tests/ECMInstallIconsTest/expected-tree/v1-icons/hicolor/icon-theme.cache Binary files differnew file mode 100644 index 00000000..ab56337b --- /dev/null +++ b/tests/ECMInstallIconsTest/expected-tree/v1-icons/hicolor/icon-theme.cache diff --git a/tests/ECMInstallIconsTest/hi16-actions-old-style-name.png b/tests/ECMInstallIconsTest/hi16-actions-old-style-name.png Binary files differnew file mode 100644 index 00000000..ed9a1181 --- /dev/null +++ b/tests/ECMInstallIconsTest/hi16-actions-old-style-name.png diff --git a/tests/ECMInstallIconsTest/subdir/16-apps-cmake.png b/tests/ECMInstallIconsTest/subdir/16-apps-cmake.png Binary files differnew file mode 100644 index 00000000..ed9a1181 --- /dev/null +++ b/tests/ECMInstallIconsTest/subdir/16-apps-cmake.png diff --git a/tests/ECMInstallIconsTest/v1-syntax-no-icons/CMakeLists.txt b/tests/ECMInstallIconsTest/v1-syntax-no-icons/CMakeLists.txt new file mode 100644 index 00000000..e0cacec2 --- /dev/null +++ b/tests/ECMInstallIconsTest/v1-syntax-no-icons/CMakeLists.txt @@ -0,0 +1 @@ +ecm_install_icons(v1-icons-dummy) diff --git a/tests/ECMPoQmToolsTest/CMakeLists.txt b/tests/ECMPoQmToolsTest/CMakeLists.txt index 15351d2f..76d80141 100644 --- a/tests/ECMPoQmToolsTest/CMakeLists.txt +++ b/tests/ECMPoQmToolsTest/CMakeLists.txt @@ -9,9 +9,13 @@ file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}") include(ECMPoQmTools) -# Should create ${CMAKE_CURRENT_BINARY_DIR}/qmloader.cpp and set QMLOADER_PATH -# to its path -ecm_create_qm_loader(QMLOADER_PATH catalog) +include(../test_helpers.cmake) + + +# +# ecm_process_po_files_as_qm +# + # Should create a process-and-install.qm file and install it ecm_process_po_files_as_qm(fr ALL @@ -24,20 +28,63 @@ ecm_process_po_files_as_qm(fr ALL PO_FILES only-process.po ) + + +# +# ecm_install_po_files_as_qm +# + # Should create a bunch of .qm files and install them in share/locale. # Should ignore files directly under po/ as well as directories under po/ which # do not contain any .po files. ecm_install_po_files_as_qm(po) + # Should create a bunch of .qm files and install them in # ${CMAKE_INSTALL_LOCALEDIR} set(CMAKE_INSTALL_LOCALEDIR custom-dir1) ecm_install_po_files_as_qm(po-custom-dir1) + # Should create a bunch of .qm files and install them in # ${LOCALE_INSTALL_DIR} set(LOCALE_INSTALL_DIR custom-dir2) ecm_install_po_files_as_qm(po-custom-dir2) -# this will be run by CTest -configure_file(check_tree.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/check_tree.cmake" @ONLY) +unset(CMAKE_INSTALL_LOCALEDIR) +unset(LOCALE_INSTALL_DIR) + + + +# +# ecm_create_qm_loader +# + +find_package(Qt5Core CONFIG REQUIRED) +ecm_install_po_files_as_qm(tr_test-po) + + +set(tr_test_SRCS + tr_test.cpp +) +ecm_create_qm_loader(tr_test_SRCS catalog) +add_executable(tr_test ${tr_test_SRCS}) +target_link_libraries(tr_test PRIVATE Qt5::Core) + + +# This is not something we want people to do (putting the ecm_create_qm_loader +# call in one CMakeLists.txt file and the target it is used for in another), +# but it's unfortunately something projects have done and we need to keep them +# building +unset(QMLOADER_FILES) +ecm_create_qm_loader(QMLOADER_FILES catalog) +assert_var_defined(QMLOADER_FILES) +add_subdirectory(subdir) + + + +file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check_conf.cmake" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/check_conf.cmake.in" +) +configure_file(check.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/check.cmake" @ONLY) diff --git a/tests/ECMPoQmToolsTest/check_tree.cmake.in b/tests/ECMPoQmToolsTest/check.cmake.in index 9f4f7c0d..ab434d2e 100644 --- a/tests/ECMPoQmToolsTest/check_tree.cmake.in +++ b/tests/ECMPoQmToolsTest/check.cmake.in @@ -1,6 +1,6 @@ set(BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@") set(ACTUAL_TREE "@CMAKE_INSTALL_PREFIX@") -set(QMLOADER_PATH "@QMLOADER_PATH@") +include("${BINARY_DIR}/check_conf.cmake") set(fail OFF) @@ -9,27 +9,21 @@ macro(mark_failed msg) set(fail ON) endmacro() -macro(check_strequal var expected) - if (NOT "${${var}}" STREQUAL "${expected}") - mark_failed("${var} is:\n \"${${var}}\"\nExpected:\n \"${expected}\"") - endif() -endmacro() - macro(check_exists file) + message(STATUS "Checking for ${file}") if (NOT EXISTS ${file}) mark_failed("File \"${file}\" does not exist") endif() endmacro() -check_exists(${BINARY_DIR}/ECMQmLoader.cpp) -check_strequal(QMLOADER_PATH "${BINARY_DIR}/ECMQmLoader.cpp") - check_exists(${BINARY_DIR}/fr/only-process.qm) set(exp_files "share/locale/fr/LC_MESSAGES/process-and-install.qm" "share/locale/es/LC_MESSAGES/install-test.qm" "share/locale/fr/LC_MESSAGES/install-test.qm" + "share/locale/en/LC_MESSAGES/catalog.qm" + "share/locale/de/LC_MESSAGES/catalog.qm" "custom-dir1/es/LC_MESSAGES/custom-dir1-install-test.qm" "custom-dir1/fr/LC_MESSAGES/custom-dir1-install-test.qm" "custom-dir2/es/LC_MESSAGES/custom-dir2-install-test.qm" @@ -54,6 +48,32 @@ if(NOT exp_files STREQUAL actual_files) set(fail ON) endif() endforeach() +else() + message(STATUS "Installed translations in expected locations") +endif() + +# we know we can modify the executable environment on Linux +if("@CMAKE_SYSTEM_NAME@" STREQUAL "Linux") + set(exp_output_en "english text:english plural form 5") + set(exp_output_de "german text:german plural form 5") + # no french translation provided -> english fallback + set(exp_output_fr "${exp_output_en}") + foreach(exec TR_TEST TR_TEST_SUBDIR) + foreach(lang en de fr) + execute_process( + COMMAND "${CMAKE_COMMAND}" -E env "XDG_DATA_DIRS=${ACTUAL_TREE}/share" + LANGUAGE=${lang} "${${exec}_EXEC}" + OUTPUT_VARIABLE output + ) + string(STRIP "${output}" stripped_output) + if(NOT stripped_output STREQUAL exp_output_${lang}) + message(WARNING "${exec}[${lang}] output was \"${stripped_output}\", but expected \"${exp_output_${lang}}\"") + set(fail ON) + else() + message(STATUS "${exec}[${lang}] output was \"${stripped_output}\", as expected") + endif() + endforeach() + endforeach() endif() if (fail) diff --git a/tests/ECMPoQmToolsTest/check_conf.cmake.in b/tests/ECMPoQmToolsTest/check_conf.cmake.in new file mode 100644 index 00000000..9ab02e72 --- /dev/null +++ b/tests/ECMPoQmToolsTest/check_conf.cmake.in @@ -0,0 +1,2 @@ +set(TR_TEST_EXEC "$<TARGET_FILE:tr_test>") +set(TR_TEST_SUBDIR_EXEC "$<TARGET_FILE:tr_test_subdir>") diff --git a/tests/ECMPoQmToolsTest/subdir/CMakeLists.txt b/tests/ECMPoQmToolsTest/subdir/CMakeLists.txt new file mode 100644 index 00000000..ee06b971 --- /dev/null +++ b/tests/ECMPoQmToolsTest/subdir/CMakeLists.txt @@ -0,0 +1,5 @@ +# QMLOADER_FILES comes from parent CMakeLists.txt. This is not something we +# want people to do, but it's unfortunately something projects have done and we +# need to keep them building +add_executable(tr_test_subdir ../tr_test.cpp ${QMLOADER_FILES}) +target_link_libraries(tr_test_subdir PRIVATE Qt5::Core) diff --git a/tests/ECMPoQmToolsTest/tr_test-po/de/catalog.po b/tests/ECMPoQmToolsTest/tr_test-po/de/catalog.po new file mode 100644 index 00000000..6f3e328f --- /dev/null +++ b/tests/ECMPoQmToolsTest/tr_test-po/de/catalog.po @@ -0,0 +1,22 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Language: de\n" +"X-Qt-Contexts: true\n" + +#: main.cpp:12 +msgctxt "testcontext|" +msgid "test string" +msgstr "german text" + +#: main.cpp:13 +#, qt-format +#| msgid "test plural" +msgctxt "testcontext|" +msgid "test plural %n" +msgid_plural "test plural %n" +msgstr[0] "german singular form %n" +msgstr[1] "german plural form %n" diff --git a/tests/ECMPoQmToolsTest/tr_test-po/en/catalog.po b/tests/ECMPoQmToolsTest/tr_test-po/en/catalog.po new file mode 100644 index 00000000..2a7b6d28 --- /dev/null +++ b/tests/ECMPoQmToolsTest/tr_test-po/en/catalog.po @@ -0,0 +1,22 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Language: en\n" +"X-Qt-Contexts: true\n" + +#: main.cpp:12 +msgctxt "testcontext|" +msgid "test string" +msgstr "english text" + +#: main.cpp:13 +#, qt-format +#| msgid "test plural" +msgctxt "testcontext|" +msgid "test plural %n" +msgid_plural "test plural %n" +msgstr[0] "english singular form %n" +msgstr[1] "english plural form %n" diff --git a/tests/ECMPoQmToolsTest/tr_test.cpp b/tests/ECMPoQmToolsTest/tr_test.cpp new file mode 100644 index 00000000..22101263 --- /dev/null +++ b/tests/ECMPoQmToolsTest/tr_test.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2015 Alex Merry <alex.merry@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 <QCoreApplication> +#include <QTextStream> + +#include <stdio.h> + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + + QTextStream output(stdout); + + output << QCoreApplication::translate("testcontext", "test string") << ":"; + output << QCoreApplication::translate("testcontext", "test plural %n", 0, 5) << '\n'; + + return 0; +} diff --git a/tests/ECMQtDeclareLoggingCategoryTest/CMakeLists.txt b/tests/ECMQtDeclareLoggingCategoryTest/CMakeLists.txt new file mode 100644 index 00000000..15ece187 --- /dev/null +++ b/tests/ECMQtDeclareLoggingCategoryTest/CMakeLists.txt @@ -0,0 +1,42 @@ +project(ECMQtDeclareLoggingCategoryTest) +cmake_minimum_required(VERSION 2.8.12) +set(ECM_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../modules") + +set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR}) + +include(ECMQtDeclareLoggingCategory) + +ecm_qt_declare_logging_category( + sources + HEADER "log1.h" + IDENTIFIER "log1" + CATEGORY_NAME "log.one" +) + +ecm_qt_declare_logging_category( + sources + HEADER "log2.h" + IDENTIFIER "foo::bar::log2" + CATEGORY_NAME "log.two" +) + +ecm_qt_declare_logging_category( + sources + HEADER "${CMAKE_CURRENT_BINARY_DIR}/log3.h" + IDENTIFIER "log3" + CATEGORY_NAME "three" + DEFAULT_SEVERITY Critical +) + +find_package(Qt5Core REQUIRED) + +add_executable(testmain testmain.cpp ${sources}) +target_include_directories(testmain + PRIVATE + "${CMAKE_CURRENT_BINARY_DIR}" +) +target_link_libraries(testmain + PRIVATE + Qt5::Core +) + diff --git a/tests/ECMQtDeclareLoggingCategoryTest/testmain.cpp b/tests/ECMQtDeclareLoggingCategoryTest/testmain.cpp new file mode 100644 index 00000000..4abcd527 --- /dev/null +++ b/tests/ECMQtDeclareLoggingCategoryTest/testmain.cpp @@ -0,0 +1,108 @@ +/* + * 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 <QCoreApplication> + +#include "log1.h" +#include "log2.h" +#include "log3.h" + +#include <iostream> + +int main(int argc, char **argv) { + QCoreApplication qapp(argc, argv); + + bool success = true; + + // NB: we cannot test against QtInfoMsg, as that (a) does not exist before + // Qt 5.5, and (b) has incorrect semantics in Qt 5.5, in that it is + // treated as more severe than QtCriticalMsg. + + if (log1().categoryName() != QLatin1String("log.one")) { + qWarning("log1 category was \"%s\", expected \"log.one\"", log1().categoryName()); + success = false; + } +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) + if (!log1().isDebugEnabled()) { + qWarning("log1 debug messages were not enabled"); + success = false; + } +#else + if (log1().isDebugEnabled()) { + qWarning("log1 debug messages were enabled"); + success = false; + } + if (!log1().isWarningEnabled()) { + qWarning("log1 warning messages were not enabled"); + success = false; + } +#endif + + if (foo::bar::log2().categoryName() != QLatin1String("log.two")) { + qWarning("log2 category was \"%s\", expected \"log.two\"", foo::bar::log2().categoryName()); + success = false; + } +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) + if (!foo::bar::log2().isDebugEnabled()) { + qWarning("log2 debug messages were not enabled"); + success = false; + } +#else + if (foo::bar::log2().isDebugEnabled()) { + qWarning("log2 debug messages were enabled"); + success = false; + } + if (!foo::bar::log2().isWarningEnabled()) { + qWarning("log2 warning messages were not enabled"); + success = false; + } +#endif + + if (log3().categoryName() != QLatin1String("three")) { + qWarning("log3 category was \"%s\", expected \"three\"", log3().categoryName()); + success = false; + } +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) + if (!log3().isDebugEnabled()) { + qWarning("log3 debug messages were not enabled"); + success = false; + } +#else + if (log3().isDebugEnabled()) { + qWarning("log3 debug messages were enabled"); + success = false; + } + if (log3().isWarningEnabled()) { + qWarning("log3 warning messages were enabled"); + success = false; + } + if (!log3().isCriticalEnabled()) { + qWarning("log3 critical messages were not enabled"); + success = false; + } +#endif + + return success ? 0 : 1; +} diff --git a/tests/ExecuteKDEModules/CMakeLists.txt b/tests/ExecuteKDEModules/CMakeLists.txt index d70ea908..69a19a31 100644 --- a/tests/ExecuteKDEModules/CMakeLists.txt +++ b/tests/ExecuteKDEModules/CMakeLists.txt @@ -7,11 +7,12 @@ set(all_kde_modules KDECMakeSettings KDECompilerSettings KDEFrameworkCompilerSettings + ECMMarkNonGuiExecutable ) set(ECM_KDE_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../kde-modules) set(ECM_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../modules) -set(CMAKE_MODULE_PATH "${ECM_KDE_MODULE_DIR}") +set(CMAKE_MODULE_PATH "${ECM_KDE_MODULE_DIR}" "${ECM_MODULE_DIR}") foreach(module ${all_kde_modules}) message(STATUS "module: ${module}") @@ -19,4 +20,6 @@ foreach(module ${all_kde_modules}) endforeach() add_executable(dummy main.c) +ecm_mark_nongui_executable(dummy) + set_target_properties(dummy PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/test_helpers.cmake b/tests/test_helpers.cmake index 73be343e..d9314d25 100644 --- a/tests/test_helpers.cmake +++ b/tests/test_helpers.cmake @@ -62,3 +62,31 @@ macro(assert_var_absolute_path varname) endif() endmacro() +function(assert_vars_setequal varname exp_varname) + if(ARGC LESS 3 OR NOT "${ARGV2}" STREQUAL "ALLOW_UNDEFINED") + assert_var_defined(${varname}) + endif() + # need real variables + set(list1 "${${varname}}") + set(list2 "${${exp_varname}}") + list(LENGTH list1 list1_len) + list(LENGTH list2 list2_len) + set(same_els FALSE) + if(list1_len EQUAL list2_len) + set(same_els TRUE) + foreach(item ${list1}) + list(FIND list2 "${item}" pos) + if(pos EQUAL "-1") + set(same_els FALSE) + break() + else() + # deal nicely with duplicates + list(REMOVE_AT list2 "${pos}") + endif() + endforeach() + endif() + if(NOT same_els) + message(SEND_ERROR "${varname} is '${${varname}}', expecting '${${exp_varname}}'.") + endif() +endfunction() + diff --git a/toolchain/Android.cmake b/toolchain/Android.cmake new file mode 100644 index 00000000..a60771bc --- /dev/null +++ b/toolchain/Android.cmake @@ -0,0 +1,190 @@ +#.rst: +# AndroidToolchain +# ---------------- +# +# Enable easy compilation of cmake projects on Android. +# +# By using this android toolchain, the projects will be set up to compile the +# specified project targeting an Android platform, depending on its input. +# Furthermore, if desired, an APK can be directly generated by using the +# `androiddeployqt <http://doc.qt.io/qt-5/deployment-android.html>`_ tool. +# +# .. note:: +# +# This module requires CMake 3.1. +# +# Since 1.7.0. +# +# Usage +# ===== +# +# To use this file, you need to set the ``CMAKE_TOOLCHAIN_FILE`` to point to +# ``AndroidToolchain.cmake`` on the command line:: +# +# cmake -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/AndroidToolchain.cmake +# +# You will also need to provide the locations of the Android NDK and SDK. This +# can be done on the commandline or with environment variables; in either case +# the variable names are: +# +# ``ANDROID_NDK`` +# The NSK root path. +# ``ANDROID_SDK_ROOT`` +# The SSK root path. +# +# Additional options are specified as cache variables (eg: on the command line): +# +# ``ANDROID_ARCHITECTURE`` +# The architecture to compile for. Default: ``arm``. +# ``ANDROID_TOOLCHAIN`` +# The toolchain to use. See the ``toolchains`` directory of the NDK. +# Default: ``arm-linux-androideabi``. +# ``ANDROID_ABI`` +# The ABI to use. See the ``sources/cxx-stl/gnu-libstdc++/*/libs`` +# directories in the NDK. Default: ``armeabi-v7a``. +# ``ANDROID_GCC_VERSION`` +# The GCC version to use. Default: ``4.9``. +# ``ANDROID_API_LEVEL`` +# The `API level +# <http://developer.android.com/guide/topics/manifest/uses-sdk-element.html>`_ +# to require. Default: ``14``. +# ``ANDROID_SDK_BUILD_TOOLS_REVISION`` +# The build tools version to use. Default: ``21.1.1``. +# +# Deploying Qt Applications +# ========================= +# +# After building the application, you will need to generate an APK that can be +# deployed to an Android device. This module integrates androiddeployqt support +# to help with this for Qt-based projects. To enable this, set the +# ``QTANDROID_EXPORTED_TARGET`` variable to the target you wish to export as an +# APK, as well as ``ANDROID_APK_DIR`` to a directory containing some basic +# information. This will create a ``create-apk-<target>`` target that will +# generate the APK file. See the `Qt on Android deployment documentation +# <http://doc.qt.io/qt-5/deployment-android.html>`_ for more information. +# +# For example, you could do:: +# +# cmake \ +# -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/AndroidToolchain.cmake \ +# -DQTANDROID_EXPORTED_TARGET=myapp \ +# -DANDROID_APK_DIR=myapp-apk +# make +# make create-apk-myapp +# +# The APK would then be found in ``myapp_build_apk/bin`` in the build directory. + +# ============================================================================= +# Copyright 2014 Aleix Pol i Gonzalez <aleixpol@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +# License text for the above reference.) + +cmake_minimum_required(VERSION "3.1") + +#input +set(ANDROID_NDK "$ENV{ANDROID_NDK}" CACHE path "Android NDK path") +set(ANDROID_SDK_ROOT "$ENV{ANDROID_SDK_ROOT}" CACHE path "Android SDK path") +set(ANDROID_ARCHITECTURE "arm" CACHE string "Used Architecture, related to the ABI and TOOLCHAIN") +set(ANDROID_TOOLCHAIN "arm-linux-androideabi" CACHE string "Used SDK") +set(ANDROID_ABI "armeabi-v7a" CACHE string "Used ABI") +set(ANDROID_GCC_VERSION "4.9" CACHE string "Used GCC version" ) +set(ANDROID_API_LEVEL "14" CACHE string "Android API Level") +set(ANDROID_SDK_BUILD_TOOLS_REVISION "21.1.1" CACHE string "Android API Level") + +set(_HOST "${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}") +string(TOLOWER "${_HOST}" _HOST) + +get_filename_component(_CMAKE_ANDROID_DIR "${CMAKE_TOOLCHAIN_FILE}" PATH) + +cmake_policy(SET CMP0011 OLD) +cmake_policy(SET CMP0017 OLD) + +set(CMAKE_SYSROOT + "${ANDROID_NDK}/platforms/android-${ANDROID_API_LEVEL}/arch-${ANDROID_ARCHITECTURE}") +if(NOT EXISTS ${CMAKE_SYSROOT}) + message(FATAL_ERROR "Couldn't find the Android NDK Root in ${CMAKE_SYSROOT}") +endif() + +#actual code +SET(CMAKE_SYSTEM_NAME Android) +SET(CMAKE_SYSTEM_VERSION 1) + +set(ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN}-${ANDROID_GCC_VERSION}/prebuilt/${_HOST}/bin") +set(ANDROID_LIBS_ROOT "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_GCC_VERSION}") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "${ANDROID_TOOLCHAIN_ROOT}") +set(ANDROID_LIBRARIES_PATH + "${CMAKE_SYSROOT}/usr/lib") +set(CMAKE_SYSTEM_LIBRARY_PATH + ${ANDROID_LIBRARIES_PATH} + "${ANDROID_LIBS_ROOT}/libs/${ANDROID_ABI}/" +) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so") +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +find_library(GNUSTL_SHARED gnustl_shared) +if(NOT GNUSTL_SHARED) + message(FATAL_ERROR "you need gnustl_shared: ${CMAKE_SYSTEM_LIBRARY_PATH}") +endif() +include_directories(SYSTEM + "${CMAKE_SYSROOT}/usr/include" + "${ANDROID_LIBS_ROOT}/include/" + "${ANDROID_LIBS_ROOT}/libs/${ANDROID_ABI}/include" +) + +# needed for Qt to define Q_OS_ANDROID +add_definitions(-DANDROID) + +link_directories(${CMAKE_SYSTEM_LIBRARY_PATH}) + +set(CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN}-gcc") +set(CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN}-g++") + +SET(CMAKE_FIND_ROOT_PATH ${ANDROID_NDK}) +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(CMAKE_EXE_LINKER_FLAGS "${GNUSTL_SHARED} -Wl,-rpath-link,${ANDROID_LIBRARIES_PATH} -llog -lz -lm -ldl -lc -lgcc" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "") + +#we want executables to be shared libraries, hooks will invoke the exported cmake function +set(CMAKE_CXX_LINK_EXECUTABLE + "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" +) + +######### generation + +set(CREATEAPK_TARGET_NAME "create-apk-${QTANDROID_EXPORTED_TARGET}") +# Need to ensure we only get in here once, as this file is included twice: +# from CMakeDetermineSystem.cmake and from CMakeSystem.cmake generated within the +# build directory. +if(DEFINED QTANDROID_EXPORTED_TARGET AND NOT TARGET ${CREATEAPK_TARGET_NAME}) + if(NOT EXISTS "${ANDROID_APK_DIR}/AndroidManifest.xml") + message(FATAL_ERROR "Define an apk dir to initialize from using -DANDROID_APK_DIR=<path>. The specified directory must contain the AndroidManifest.xml file.") + endif() + + find_package(Qt5Core REQUIRED) + + set(EXPORT_DIR "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}_build_apk/") + set(EXECUTABLE_DESTINATION_PATH "${EXPORT_DIR}/libs/${ANDROID_ABI}/lib${QTANDROID_EXPORTED_TARGET}.so") + configure_file("${_CMAKE_ANDROID_DIR}/deployment-file.json.in" "${QTANDROID_EXPORTED_TARGET}-deployment.json.in") + + add_custom_target(${CREATEAPK_TARGET_NAME} + COMMAND cmake -E echo "Generating $<TARGET_NAME:${QTANDROID_EXPORTED_TARGET}> with $<TARGET_FILE_DIR:Qt5::qmake>/androiddeployqt" + COMMAND cmake -E copy_directory "${ANDROID_APK_DIR}" "${EXPORT_DIR}" + COMMAND cmake -E copy "$<TARGET_FILE:${QTANDROID_EXPORTED_TARGET}>" "${EXECUTABLE_DESTINATION_PATH}" + COMMAND cmake -DINPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json.in" -DOUTPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json" "-DTARGET_DIR=$<TARGET_FILE_DIR:${QTANDROID_EXPORTED_TARGET}>" "-DTARGET_NAME=${QTANDROID_EXPORTED_TARGET}" -P ${_CMAKE_ANDROID_DIR}/specifydependencies.cmake + COMMAND $<TARGET_FILE_DIR:Qt5::qmake>/androiddeployqt --input "${QTANDROID_EXPORTED_TARGET}-deployment.json" --output "${EXPORT_DIR}" --deployment bundled "\\$(ARGS)" + ) +else() + message(STATUS "You can export a target by specifying -DQTANDROID_EXPORTED_TARGET=<targetname>") +endif() diff --git a/toolchain/deployment-file.json.in b/toolchain/deployment-file.json.in new file mode 100644 index 00000000..9367bc1b --- /dev/null +++ b/toolchain/deployment-file.json.in @@ -0,0 +1,15 @@ +{ + "qt": "@_qt5Core_install_prefix@", + "sdk": "@ANDROID_SDK_ROOT@", + "ndk": "@ANDROID_NDK@", + "toolchain-prefix": "@ANDROID_TOOLCHAIN@", + "tool-prefix": "@ANDROID_TOOLCHAIN@", + "toolchain-version": "@ANDROID_GCC_VERSION@", + "ndk-host": "@_HOST@", + "target-architecture": "@ANDROID_ABI@", + "application-binary": "@EXECUTABLE_DESTINATION_PATH@", + "android-extra-libs": "##EXTRALIBS##", + "android-extra-plugins": "@CMAKE_INSTALL_PREFIX@/share,@CMAKE_INSTALL_PREFIX@/lib/qml", + "android-package-source-directory": "@ANDROID_APK_DIR@", + "sdkBuildToolsRevision": "@ANDROID_SDK_BUILD_TOOLS_REVISION@" +} diff --git a/toolchain/specifydependencies.cmake b/toolchain/specifydependencies.cmake new file mode 100644 index 00000000..21b169ae --- /dev/null +++ b/toolchain/specifydependencies.cmake @@ -0,0 +1,22 @@ +file(READ "${TARGET_DIR}/CMakeFiles/${TARGET_NAME}.dir/link.txt" out) + +string(FIND "${out}" "-o ${TARGET_NAME}" POS) #we trim the initial arguments, we want the ones in the end. we find the target +string(SUBSTRING "${out}" ${POS} -1 out) #we +string(REGEX MATCHALL " /.+\\.so" outout "${out}") +string(STRIP "${outout}" outout) +string(REPLACE " /" ";/" outout "${outout}") + +set(extralibs) +foreach(lib IN LISTS outout) #now we filter Qt5 libraries, because Qt wants to take care about these itself + if(NOT ${lib} MATCHES ".*/libQt5.*") + if(extralibs) + set(extralibs "${extralibs},${lib}") + else() + set(extralibs "${lib}") + endif() + endif() +endforeach() + +file(READ "${INPUT_FILE}" CONTENTS) +string(REPLACE "##EXTRALIBS##" "${extralibs}" NEWCONTENTS "${CONTENTS}") +file(WRITE "${OUTPUT_FILE}" ${NEWCONTENTS}) |