diff --git a/docs/module/ECMConfiguredInstall.rst b/docs/module/ECMConfiguredInstall.rst new file mode 100644 index 0000000..ee333e6 --- /dev/null +++ b/docs/module/ECMConfiguredInstall.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../modules/ECMConfiguredInstall.cmake diff --git a/modules/ECMConfiguredInstall.cmake b/modules/ECMConfiguredInstall.cmake new file mode 100644 index 0000000..52ab517 --- /dev/null +++ b/modules/ECMConfiguredInstall.cmake @@ -0,0 +1,98 @@ +#.rst: +# ECMConfiguredInstall +# -------------------- +# +# Take a list of files, runs configure_file and installs the resultant configured file in the given location. +# +# Any suffix of ".in" in the passed file names wil be stripped from the file name at the installed location. +# :: +# ecm_install_configured_files( +# TEMPLATES [ [...]] +# DESTINATION +# [COPYONLY] +# [ESCAPE_QUOTES] +# [@ONLY] +# [COMPONENT ]) +# +# Example usage: +# +# .. code-block:: cmake +# +# ecm_install_configured_files(TEMPLATES foo.txt.in DESTINATION ${KDE_INSTALL_DATADIR} @ONLY) +# +# This wil install the file as foo.txt with any cmake variable replacements made into the data directory. +# +# Since 5.70.0. + +# Copyright 2020 David Edmundson +# +# 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. + +function(ecm_install_configured_files) + set(options COPYONLY ESCAPE_QUOTES @ONLY) + set(oneValueArgs DESTINATION COMPONENT) + set(multiValueArgs TEMPLATES) + + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + + + if(ARGS_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown arguments given to ecm_install_configured_file(): \"${ARGS_UNPARSED_ARGUMENTS}\"") + endif() + + if (NOT ARGS_DESTINATION) + message(FATAL_ERROR "missing DESTINATION argument to ECMConfiguredInstall"); + endif() + + foreach(_template ${ARGS_TEMPLATES}) + # convert absolute paths + get_filename_component(_name ${_template} NAME) + + string(REGEX REPLACE "\\.in$" "" _name ${_name}) + + set(_out_file ${CMAKE_CURRENT_BINARY_DIR}/${_name}) + + set(_configure_args) + if (ARGS_COPY_ONLY) + list(APPEND _configure_args COPY_ONLY) + endif() + if (ARGS_ESCAPE_QUOTES) + list(APPEND _configure_args ESCAPE_QUOTES) + endif() + if (ARGS_@ONLY) + list(APPEND _configure_args @ONLY) + endif() + + configure_file(${_template} ${_out_file} ${_configure_args}) + + if (DEFINED ARGS_COMPONENT) + set(_component COMPONENT ${ARGS_COMPONENT}) + else() + set(_component) + endif() + + install(FILES ${_out_file} DESTINATION ${ARGS_DESTINATION} ${_component}) + endforeach() +endfunction() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3977193..2e69e57 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,224 +1,234 @@ #============================================================================= # Copyright 2011 Alex Neundorf # Copyright 2014-2015 Alex Merry # # 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. #============================================================================= # We need to set a language to find CMake packages installed in # architecture-dependent locations (like /usr/lib64). # We only set this for the tests, making sure it does not interfere # with other files (as ECM itself is architecture-independent). project(ECMTests C) find_package(Qt5LinguistTools CONFIG) set_package_properties( Qt5LinguistTools PROPERTIES URL "https://www.qt.io/" DESCRIPTION "Qt5 linguist tools." TYPE OPTIONAL PURPOSE "Required to run tests for the ECMPoQmTools module." ) find_package(Qt5Core CONFIG) set_package_properties( Qt5Core PROPERTIES URL "https://www.qt.io/" DESCRIPTION "Qt5 core library." TYPE OPTIONAL PURPOSE "Required to run tests for the ECMQtDeclareLoggingCategory module, and for some tests of the KDEInstallDirs module." ) add_subdirectory(ECMAddTests) add_subdirectory(ECMGenerateExportHeaderTest) add_subdirectory(ECMGenerateHeadersTest) add_subdirectory(ECMSetupVersionTest) add_subdirectory(ECMGeneratePkgConfigFile) # a macro for tests that have a simple format where the name matches the # directory and project macro(add_test_variant NAME BASE COMMAND) string(REPLACE "." "/" src_dir "${BASE}") string(REPLACE "." "/" build_dir "${NAME}") string(REGEX REPLACE "[^.]*\\." "" proj "${NAME}") add_test(${NAME} ${CMAKE_CTEST_COMMAND} --build-and-test "${CMAKE_CURRENT_SOURCE_DIR}/${src_dir}" "${CMAKE_CURRENT_BINARY_DIR}/${build_dir}" --build-two-config --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-project ${proj} ${${NAME}_EXTRA_OPTIONS} --test-command ${COMMAND} ${ARGN}) endmacro() macro(add_test_macro NAME) add_test_variant("${NAME}" "${NAME}" ${ARGN}) endmacro() list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/find-modules) # Skip if PyQt not available find_file(SIP_Qt5Core_Mod_FILE NAMES QtCoremod.sip PATH_SUFFIXES share/sip/PyQt5/QtCore ) if(NOT SIP_Qt5Core_Mod_FILE) message(STATUS "WARNING: skipping tests that require PyQt") else() find_package(PythonModuleGeneration) foreach(pyversion 2 3) if (GPB_PYTHON${pyversion}_COMMAND) if (pythonCommands) list(APPEND pythonCommands " && ") endif() set(pythonCommands ${GPB_PYTHON${pyversion}_COMMAND} "${CMAKE_CURRENT_SOURCE_DIR}/GenerateSipBindings/testscript.py" "${CMAKE_CURRENT_BINARY_DIR}/GenerateSipBindings/py${pyversion}" ) endif() endforeach() if (pythonCommands) add_test_macro(GenerateSipBindings ${pythonCommands}) else() message(STATUS "WARNING: skipping GenerateSipBindings test") endif() endif() add_test_macro(ExecuteCoreModules dummy) add_test_macro(ExecuteKDEModules dummy) add_test_macro(KDEFetchTranslations dummy) add_test_variant(KDEInstallDirsTest.vars_in_sync_no_args KDEInstallDirsTest.vars_in_sync dummy) add_test_macro(KDEInstallDirsTest.not_cache_variable dummy) set(KDEInstallDirsTest.vars_in_sync_kde_arg_EXTRA_OPTIONS --build-options -DKDE_INSTALL_BINDIR=altbin -DBINDIR_expected_value=altbin -DCMAKE_WARN_DEPRECATED=TRUE ) add_test_variant(KDEInstallDirsTest.vars_in_sync_kde_arg KDEInstallDirsTest.vars_in_sync dummy) set(KDEInstallDirsTest.vars_in_sync_cmake_arg_EXTRA_OPTIONS --build-options -DCMAKE_INSTALL_BINDIR=altbin -DBINDIR_expected_value=altbin -DCMAKE_WARN_DEPRECATED=TRUE ) add_test_variant(KDEInstallDirsTest.vars_in_sync_cmake_arg KDEInstallDirsTest.vars_in_sync dummy) set(KDEInstallDirsTest.vars_in_sync_oldstyle_arg_EXTRA_OPTIONS --build-options -DBIN_INSTALL_DIR=altbin -DBINDIR_expected_value=altbin -DCMAKE_WARN_DEPRECATED=TRUE ) add_test_variant(KDEInstallDirsTest.vars_in_sync_oldstyle_arg KDEInstallDirsTest.vars_in_sync dummy) set(KDEInstallDirsTest.relative_or_absolute_usr_EXTRA_OPTIONS --build-options -DCMAKE_INSTALL_PREFIX=/usr -DKDE_INSTALL_USE_QT_SYS_PATHS=FALSE -DAUTOSTARTDIR_should_be_absolute=TRUE -DCONFDIR_should_be_absolute=TRUE -DSYSCONFDIR_should_be_absolute=TRUE ) add_test_variant(KDEInstallDirsTest.relative_or_absolute_usr KDEInstallDirsTest.relative_or_absolute dummy) if (TARGET Qt5::qmake) set(KDEInstallDirsTest.relative_or_absolute_qt_EXTRA_OPTIONS --build-options -DCMAKE_INSTALL_PREFIX=/tmp -DKDE_INSTALL_USE_QT_SYS_PATHS=TRUE -DPLUGINDIR_should_be_absolute=TRUE -DQMLDIR_should_be_absolute=TRUE -DQTQCHDIR_should_be_absolute=TRUE -DQTPLUGINDIR_should_be_absolute=TRUE -DQTQUICKIMPORTSDIR_should_be_absolute=TRUE ) 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) set(ECMAddAppIconTest_EXTRA_OPTIONS --build-target all --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/ECMAddAppIconTest/InstallDirectory" ) add_test_macro(ECMAddAppIconTest ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/ECMAddAppIconTest/check_files.cmake" ) set(ECMInstallIconsTest_EXTRA_OPTIONS --build-target install --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/ECMInstallIconsTest/InstallDirectory" ) add_test_macro(ECMInstallIconsTest ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/ECMInstallIconsTest/check_tree.cmake" ) set(KDEPackageAppTemplatesTest_EXTRA_OPTIONS --build-target install --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/KDEPackageAppTemplatesTest/InstallDirectory" ) add_test_macro(KDEPackageAppTemplatesTest ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/KDEPackageAppTemplatesTest/check.cmake" ) 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.cmake" ) endif() find_package(Qt5Quick CONFIG) set_package_properties( Qt5Quick PROPERTIES URL "https://www.qt.io/" DESCRIPTION "Qt5 Quick library." TYPE OPTIONAL PURPOSE "Required to run tests for the ECMQMLModules module." ) if (TARGET Qt5::Quick) add_test_macro(ECMQMLModules dummy) endif() + +set(ECMConfiguredInstallTest_EXTRA_OPTIONS + --build-target install + --build-options + "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/ECMConfiguredInstallTest/InstallDirectory" +) +add_test_macro(ECMConfiguredInstallTest + ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/ECMConfiguredInstallTest/check_tree.cmake" +) + diff --git a/tests/ECMConfiguredInstallTest/CMakeLists.txt b/tests/ECMConfiguredInstallTest/CMakeLists.txt new file mode 100644 index 0000000..3b6d33a --- /dev/null +++ b/tests/ECMConfiguredInstallTest/CMakeLists.txt @@ -0,0 +1,21 @@ +project(ECMConfiguredInstallTest) +cmake_minimum_required(VERSION 3.5) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../modules) + +# make sure the test install dir is clean +file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}") +include(ECMConfiguredInstall) + +# run test + +set(FOO myFoo) +set(BAR myBar) + +ecm_install_configured_files(TEMPLATES configured.txt DESTINATION ${CMAKE_INSTALL_PREFIX}/test) + +ecm_install_configured_files(TEMPLATES configured_atOnly.txt.in DESTINATION ${CMAKE_INSTALL_PREFIX}/test @ONLY ESCAPE_QUOTES) + +ecm_install_configured_files(TEMPLATES multi1.txt.in ${CMAKE_CURRENT_SOURCE_DIR}/multi2.txt.in DESTINATION ${CMAKE_INSTALL_PREFIX}/test) + +# this will be run by CTest +configure_file(check_tree.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/check_tree.cmake" @ONLY) diff --git a/tests/ECMConfiguredInstallTest/check_tree.cmake.in b/tests/ECMConfiguredInstallTest/check_tree.cmake.in new file mode 100644 index 0000000..c5fe51c --- /dev/null +++ b/tests/ECMConfiguredInstallTest/check_tree.cmake.in @@ -0,0 +1,20 @@ +set(EXPECTED "@CMAKE_CURRENT_SOURCE_DIR@/expected") +set(ACTUAL "@CMAKE_INSTALL_PREFIX@") + +# Compares files in two directories, emits a fatal error if the top level files are different +# Takes a directory of expected files, and a directory of output files +function(compare_dirs expected output ) + file(GLOB files "${expected}/*") + foreach(file ${files}) + get_filename_component(name ${file} NAME) + + execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files ${file} "${output}/${name}" + RESULT_VARIABLE test_result + ) + If (NOT test_result EQUAL 0) + message(FATAL_ERROR "Test failed: ${file} doesn't match ${output}/${name}!") + endif() + endforeach() +endfunction() + +compare_dirs(${EXPECTED} ${ACTUAL}/test ) diff --git a/tests/ECMConfiguredInstallTest/configured.txt b/tests/ECMConfiguredInstallTest/configured.txt new file mode 100644 index 0000000..8dd0d5d --- /dev/null +++ b/tests/ECMConfiguredInstallTest/configured.txt @@ -0,0 +1,3 @@ +[General] +Foo=@FOO@ +Bar=${BAR} diff --git a/tests/ECMConfiguredInstallTest/configured_atOnly.txt.in b/tests/ECMConfiguredInstallTest/configured_atOnly.txt.in new file mode 100644 index 0000000..8dd0d5d --- /dev/null +++ b/tests/ECMConfiguredInstallTest/configured_atOnly.txt.in @@ -0,0 +1,3 @@ +[General] +Foo=@FOO@ +Bar=${BAR} diff --git a/tests/ECMConfiguredInstallTest/expected/configured.txt b/tests/ECMConfiguredInstallTest/expected/configured.txt new file mode 100644 index 0000000..119db8f --- /dev/null +++ b/tests/ECMConfiguredInstallTest/expected/configured.txt @@ -0,0 +1,3 @@ +[General] +Foo=myFoo +Bar=myBar diff --git a/tests/ECMConfiguredInstallTest/expected/configured_atOnly.txt b/tests/ECMConfiguredInstallTest/expected/configured_atOnly.txt new file mode 100644 index 0000000..68a37bf --- /dev/null +++ b/tests/ECMConfiguredInstallTest/expected/configured_atOnly.txt @@ -0,0 +1,3 @@ +[General] +Foo=myFoo +Bar=${BAR} diff --git a/tests/ECMConfiguredInstallTest/expected/multi1.txt b/tests/ECMConfiguredInstallTest/expected/multi1.txt new file mode 100644 index 0000000..a8f6a10 --- /dev/null +++ b/tests/ECMConfiguredInstallTest/expected/multi1.txt @@ -0,0 +1,2 @@ +TestMulti1 +Foo=myFoo diff --git a/tests/ECMConfiguredInstallTest/expected/multi2.txt b/tests/ECMConfiguredInstallTest/expected/multi2.txt new file mode 100644 index 0000000..b396657 --- /dev/null +++ b/tests/ECMConfiguredInstallTest/expected/multi2.txt @@ -0,0 +1,2 @@ +TestMulti2 +Foo=myFoo diff --git a/tests/ECMConfiguredInstallTest/multi1.txt.in b/tests/ECMConfiguredInstallTest/multi1.txt.in new file mode 100644 index 0000000..9e98c14 --- /dev/null +++ b/tests/ECMConfiguredInstallTest/multi1.txt.in @@ -0,0 +1,2 @@ +TestMulti1 +Foo=@FOO@ diff --git a/tests/ECMConfiguredInstallTest/multi2.txt.in b/tests/ECMConfiguredInstallTest/multi2.txt.in new file mode 100644 index 0000000..018ad63 --- /dev/null +++ b/tests/ECMConfiguredInstallTest/multi2.txt.in @@ -0,0 +1,2 @@ +TestMulti2 +Foo=@FOO@