diff options
104 files changed, 1130 insertions, 310 deletions
diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst index 8f082e8..086668c 100644 --- a/Help/command/configure_file.rst +++ b/Help/command/configure_file.rst @@ -6,9 +6,9 @@ Copy a file to another location and modify its contents. .. code-block:: cmake configure_file(<input> <output> - [FILE_PERMISSIONS <permissions>...] + [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS | + FILE_PERMISSIONS <permissions>...] [COPYONLY] [ESCAPE_QUOTES] [@ONLY] - [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ]) Copies an ``<input>`` file to an ``<output>`` file and substitutes @@ -97,8 +97,27 @@ The arguments are: If the path names an existing directory the output file is placed in that directory with the same file name as the input file. +``NO_SOURCE_PERMISSIONS`` + .. versionadded:: 3.19 + + Do not transfer the permissions of the input file to the output file. + The copied file permissions default to the standard 644 value + (-rw-r--r--). + +``USE_SOURCE_PERMISSIONS`` + .. versionadded:: 3.20 + + Transfer the permissions of the input file to the output file. + This is already the default behavior if none of the three permissions-related + keywords are given (``NO_SOURCE_PERMISSIONS``, ``USE_SOURCE_PERMISSIONS`` + or ``FILE_PERMISSIONS``). The ``USE_SOURCE_PERMISSIONS`` keyword mostly + serves as a way of making the intended behavior clearer at the call site. + ``FILE_PERMISSIONS <permissions>...`` - Use user provided permissions for the output file. + .. versionadded:: 3.20 + + Ignore the input file's permissions and use the specified ``<permissions>`` + for the output file instead. ``COPYONLY`` Copy the file without replacing any variable references or other @@ -111,18 +130,6 @@ The arguments are: Restrict variable replacement to references of the form ``@VAR@``. This is useful for configuring scripts that use ``${VAR}`` syntax. -``NO_SOURCE_PERMISSIONS`` - .. versionadded:: 3.19 - - Does not transfer the file permissions of the original file to the copy. - The copied file permissions default to the standard 644 value - (-rw-r--r--). - -``USE_SOURCE_PERMISSIONS`` - .. versionadded:: 3.20 - - Transfer the file permissions of the original file to the output file. - ``NEWLINE_STYLE <style>`` Specify the newline style for the output file. Specify ``UNIX`` or ``LF`` for ``\n`` newlines, or specify diff --git a/Help/command/file.rst b/Help/command/file.rst index 445a408..2b445c5 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -481,8 +481,8 @@ modified. file(GENERATE OUTPUT output-file <INPUT input-file|CONTENT content> [CONDITION expression] [TARGET target] - [FILE_PERMISSIONS <permissions>...] - [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS] + [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS | + FILE_PERMISSIONS <permissions>...] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ]) Generate an output file for each build configuration supported by the current @@ -524,16 +524,26 @@ from the input content to produce the output content. The options are: require a target for evaluation (e.g. ``$<COMPILE_FEATURES:...>``, ``$<TARGET_PROPERTY:prop>``). -``FILE_PERMISSIONS <permissions>...`` - Use user provided permissions for the generated file. - ``NO_SOURCE_PERMISSIONS`` + .. versionadded:: 3.20 + The generated file permissions default to the standard 644 value (-rw-r--r--). ``USE_SOURCE_PERMISSIONS`` - Transfer the file permissions of the original file to the generated file. - This option expects INPUT option. + .. versionadded:: 3.20 + + Transfer the file permissions of the ``INPUT`` file to the generated file. + This is already the default behavior if none of the three permissions-related + keywords are given (``NO_SOURCE_PERMISSIONS``, ``USE_SOURCE_PERMISSIONS`` + or ``FILE_PERMISSIONS``). The ``USE_SOURCE_PERMISSIONS`` keyword mostly + serves as a way of making the intended behavior clearer at the call site. + It is an error to specify this option without ``INPUT``. + +``FILE_PERMISSIONS <permissions>...`` + .. versionadded:: 3.20 + + Use the specified permissions for the generated file. ``NEWLINE_STYLE <style>`` .. versionadded:: 3.20 @@ -738,9 +748,9 @@ Create the given directories and their parents as needed. .. code-block:: cmake file(<COPY|INSTALL> <files>... DESTINATION <dir> + [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS] [FILE_PERMISSIONS <permissions>...] [DIRECTORY_PERMISSIONS <permissions>...] - [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS] [FOLLOW_SYMLINK_CHAIN] [FILES_MATCHING] [[PATTERN <pattern> | REGEX <regex>] diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index f103c50..5dfa894 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,7 +57,8 @@ Policies Introduced by CMake 3.21 .. toctree:: :maxdepth: 1 - CMP0121: The list command detects invalid indicies </policy/CMP0121> + CMP0122: UseSWIG use standard library name conventions for csharp language. </policy/CMP0122> + CMP0121: The list command detects invalid indicies. </policy/CMP0121> Policies Introduced by CMake 3.20 ================================= diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index cc72603..8543be3 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -864,6 +864,22 @@ object, it has the following fields: A required list of strings to search. This field supports macro expansion, and uses short-circuit evaluation. + ``"matches"`` + + ``"notMatches"`` + + Indicates that the condition searches for a regular expression in a string. + The condition object will have the following additional fields: + + ``string`` + + A required string to search. This field supports macro expansion. + + ``regex`` + + A required regular expression to search for. This field supports macro + expansion. + ``"anyOf"`` ``"allOf"`` diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 175359d..68409e1 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -155,7 +155,10 @@ Options Run tests with labels matching regular expression. This option tells CTest to run only the tests whose labels match the - given regular expression. + given regular expression. When more than one ``-L`` option is given, + a test will only be run if each regular expression matches at least one + of the test's labels (i.e. the multiple ``-L`` labels form an ``AND`` + relationship). See `Label Matching`_. ``-R <regex>, --tests-regex <regex>`` Run tests matching regular expression. @@ -173,7 +176,10 @@ Options Exclude tests with labels matching regular expression. This option tells CTest to NOT run the tests whose labels match the - given regular expression. + given regular expression. When more than one ``-LE`` option is given, + a test will only be excluded if each regular expression matches at least one + of the test's labels (i.e. the multiple ``-LE`` labels form an ``AND`` + relationship). See `Label Matching`_. ``-FA <regex>, --fixture-exclude-any <regex>`` Exclude fixtures matching ``<regex>`` from automatically adding any tests to @@ -398,6 +404,46 @@ Specify the directory in which to look for tests. .. include:: OPTIONS_HELP.txt +.. _`Label Matching`: + +Label Matching +============== + +Tests may have labels attached to them. Tests may be included +or excluded from a test run by filtering on the labels. +Each individual filter is a regular expression applied to +the labels attached to a test. + +When ``-L`` is used, in order for a test to be included in a +test run, each regular expression must match at least one +label. Using more than one ``-L`` option means "match **all** +of these". + +The ``-LE`` option works just like ``-L``, but excludes tests +rather than including them. A test is excluded if each regular +expression matches at least one label. + +If a test has no labels attached to it, then ``-L`` will never +include that test, and ``-LE`` will never exclude that test. +As an example of tests with labels, consider five tests, +with the following labels: + +* *test1* has labels *tuesday* and *production* +* *test2* has labels *tuesday* and *test* +* *test3* has labels *wednesday* and *production* +* *test4* has label *wednesday* +* *test5* has labels *friday* and *test* + +Running ``ctest`` with ``-L tuesday -L test`` will select *test2*, which has +both labels. Running CTest with ``-L test`` will select *test2* and +*test5*, because both of them have a label that matches that regular +expression. + +Because the matching works with regular expressions, take note that +running CTest with ``-L es`` will match all five tests. +To select the *tuesday* and *wednesday* tests together, use a single +regular expression that matches either of them, like ``-L "tue|wed"``. + .. _`Label and Subproject Summary`: Label and Subproject Summary diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index c3c3ca1..9261519 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -1114,6 +1114,54 @@ "type": { "type": "string", "description": "A required string specifying the type of the condition.", + "const": "matches" + }, + "string": { + "type": "string", + "description": "A required string to search. This field supports macro expansion." + }, + "regex": { + "type": "string", + "description": "A required regular expression to search for. This field supports macro expansion." + } + }, + "required": [ + "type", + "string", + "regex" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "notMatches" + }, + "string": { + "type": "string", + "description": "A required string to search. This field supports macro expansion." + }, + "regex": { + "type": "string", + "description": "A required regular expression to search for. This field supports macro expansion." + } + }, + "required": [ + "type", + "string", + "regex" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", "const": "anyOf" }, "conditions": { diff --git a/Help/policy/CMP0122.rst b/Help/policy/CMP0122.rst new file mode 100644 index 0000000..1ff8c48 --- /dev/null +++ b/Help/policy/CMP0122.rst @@ -0,0 +1,17 @@ +CMP0122 +------- + +.. versionadded:: 3.21 + +:module:`UseSWIG` use library name conventions for ``CSharp`` language. + +Starting with CMake 3.21, :module:`UseSWIG` generates now a library using +default naming conventions. This policy provides compatibility with projects +that expect the legacy behavior. + +This policy was introduced in CMake version 3.21. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst index 176447d..9991eab 100644 --- a/Help/release/3.20.rst +++ b/Help/release/3.20.rst @@ -327,3 +327,17 @@ Other Changes `cmake.org <https://cmake.org/download/>`_ have changed their naming pattern to ``cmake-$ver-windows-$arch``, where ``$arch`` is either ``x86_64`` or ``i386``. + +Updates +======= + +Changes made since CMake 3.20.0 include the following. + +3.20.1 +------ + +* The :module:`FindIntl` module in CMake 3.20.0 added checks + ``Intl_HAVE_GETTEXT_BUILTIN``, ``Intl_HAVE_DCGETTEXT_BUILTIN``, + and ``Intl_IS_BUILTIN``, but they were not implemented correctly. + These have been removed and replaced with a single ``Intl_IS_BUILT_IN`` + check, whose name is consistent with the :module:`FindIconv` module. diff --git a/Help/release/dev/UseSWIG-csharp.rst b/Help/release/dev/UseSWIG-csharp.rst new file mode 100644 index 0000000..dbbeaf1 --- /dev/null +++ b/Help/release/dev/UseSWIG-csharp.rst @@ -0,0 +1,5 @@ +UseSWIG-csharp +-------------- + +* The :module:`UseSWIG` module use now standard library name conventions for + ``CSharp`` language. See policy :policy:`CMP0122`. diff --git a/Help/release/dev/ifw-default-version-operator.rst b/Help/release/dev/ifw-default-version-operator.rst new file mode 100644 index 0000000..4aeace2 --- /dev/null +++ b/Help/release/dev/ifw-default-version-operator.rst @@ -0,0 +1,7 @@ +ifw-default-version-operator +---------------------------- + +* Names given as ``DEPENDS`` or ``DEPENDENCIES`` arguments to + :command:`cpack_ifw_configure_component` or + :command:`cpack_ifw_configure_component_group` may now contain hyphens. + This requires QtIFW 3.1 or later. diff --git a/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst b/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst index ad297c3..0d5ccd1 100644 --- a/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst +++ b/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst @@ -8,8 +8,7 @@ CMake what architecture to use for :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`. The value must be either ``arm64`` or ``x86_64``. The value of this variable should never be modified by project code. -It is meant to be set by a toolchain file specified by the -:variable:`CMAKE_TOOLCHAIN_FILE` variable, or as a cache entry -provided by the user, e.g. via ``-DCMAKE_APPLE_SILICON_PROCESSOR=...``. +It is meant to be set as a cache entry provided by the user, +e.g. via ``-DCMAKE_APPLE_SILICON_PROCESSOR=...``. See also the :envvar:`CMAKE_APPLE_SILICON_PROCESSOR` environment variable. diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index ff178f6..e87a16b 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -99,6 +99,8 @@ else() set(_CMAKE_LINKER_NAMES "ld.lld") endif() list(APPEND _CMAKE_AR_NAMES "llvm-ar") + list(APPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") + list(APPEND _CMAKE_STRIP_NAMES "llvm-strip") list(APPEND _CMAKE_NM_NAMES "llvm-nm") list(APPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump") list(APPEND _CMAKE_OBJCOPY_NAMES "llvm-objcopy") diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 0b92b6a..f61a3f2 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -62,6 +62,9 @@ PRINT *, 'INFO:compiler[Cray]' # define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) # define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) +# if defined(_RELEASE_PATCHLEVEL) +# define COMPILER_VERSION_PATCH DEC(_RELEASE_PATCHLEVEL) +# endif #elif defined(__G95__) PRINT *, 'INFO:compiler[G95]' # define COMPILER_VERSION_MAJOR DEC(__G95__) diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index d57cf18..2087a51 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -125,6 +125,11 @@ The module defines the following commands: list of dependency component or component group identifiers in QtIFW style. + .. versionadded:: 3.21 + + Component or group names listed as dependencies may contain hyphens. + This requires QtIFW 3.1 or later. + ``AUTO_DEPEND_ON`` .. versionadded:: 3.8 @@ -260,6 +265,11 @@ The module defines the following commands: list of dependency component or component group identifiers in QtIFW style. + .. versionadded:: 3.21 + + Component or group names listed as dependencies may contain hyphens. + This requires QtIFW 3.1 or later. + ``AUTO_DEPEND_ON`` .. versionadded:: 3.8 diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake index 7fe5da1..4a16e31 100644 --- a/Modules/FindDoxygen.cmake +++ b/Modules/FindDoxygen.cmake @@ -223,7 +223,8 @@ them to be separated by whitespace. CMake variables hold lists as a string with items separated by semi-colons, so a conversion needs to be performed. The ``doxygen_add_docs()`` command specifically checks the following Doxygen config options and will convert their associated CMake variable's contents into the -required form if set. +required form if set. CMake variables are named ``DOXYGEN_<name>`` for the +Doxygen settings specified here. :: diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake index a1dfed1..038f4da 100644 --- a/Modules/FindIntl.cmake +++ b/Modules/FindIntl.cmake @@ -61,24 +61,11 @@ The following cache variables may also be set: The libintl library (if any) -.. variable:: Intl_HAVE_GETTEXT_BUILTIN +.. variable:: Intl_IS_BUILT_IN .. versionadded:: 3.20 - True if gettext is in the C library - -.. variable:: Intl_HAVE_DCGETTEXT_BUILTIN - - .. versionadded:: 3.20 - - True if dcgettext is in the C library - -.. variable:: Intl_IS_BUILTIN - - .. versionadded:: 3.20 - - whether intl is a part of the C library determined from the result of - Intl_HAVE_GETTEXT_BUILTIN and Intl_HAVE_DCGETTEXT_BUILTIN + whether ``intl`` is a part of the C library. .. note:: On some platforms, such as Linux with GNU libc, the gettext @@ -95,44 +82,60 @@ The following cache variables may also be set: ``msgfmt``, etc.), use :module:`FindGettext`. #]=======================================================================] - -# Written by Roger Leigh <rleigh@codelibre.net> - include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake) - -# Check if we have libintl is a part of libc -cmake_push_check_state(RESET) -set(CMAKE_REQUIRED_QUIET TRUE) -check_symbol_exists(gettext libintl.h Intl_HAVE_GETTEXT_BUILTIN) -check_symbol_exists(dcgettext libintl.h Intl_HAVE_DCGETTEXT_BUILTIN) # redundant check -cmake_pop_check_state() - -if(Intl_HAVE_GETTEXT_BUILTIN AND Intl_HAVE_DCGETTEXT_BUILTIN) - set(Intl_IS_BUILTIN TRUE) +if(CMAKE_C_COMPILER_LOADED) + include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake) +elseif(CMAKE_CXX_COMPILER_LOADED) + include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXSourceCompiles.cmake) else() - set(Intl_IS_BUILTIN FALSE) + # If neither C nor CXX are loaded, implicit intl makes no sense. + set(Intl_IS_BUILT_IN FALSE) endif() -# Find include directory -find_path(Intl_INCLUDE_DIR - NAMES "libintl.h" - DOC "libintl include directory") -mark_as_advanced(Intl_INCLUDE_DIR) +# Check if Intl is built in to the C library. +if(NOT DEFINED Intl_IS_BUILT_IN) + if(NOT DEFINED Intl_INCLUDE_DIR AND NOT DEFINED Intl_LIBRARY) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_QUIET TRUE) + set(Intl_IMPLICIT_TEST_CODE [[ +#include <libintl.h> +int main(void) { + gettext(""); + dgettext("", ""); + dcgettext("", "", 0); + return 0; +} +]]) + if(CMAKE_C_COMPILER_LOADED) + check_c_source_compiles("${Intl_IMPLICIT_TEST_CODE}" Intl_IS_BUILT_IN) + else() + check_cxx_source_compiles("${Intl_IMPLICIT_TEST_CODE}" Intl_IS_BUILT_IN) + endif() + cmake_pop_check_state() + else() + set(Intl_IS_BUILT_IN FALSE) + endif() +endif() -# Find all Intl libraries -if(NOT Intl_IS_BUILTIN) - set(Intl_LIBRARY_NAMES "intl" "libintl") +set(_Intl_REQUIRED_VARS) +if(Intl_IS_BUILT_IN) + set(_Intl_REQUIRED_VARS _Intl_IS_BUILT_IN_MSG) + set(_Intl_IS_BUILT_IN_MSG "built in to C library") else() - set(Intl_LIBRARY_NAMES "c") -endif() + set(_Intl_REQUIRED_VARS Intl_LIBRARY Intl_INCLUDE_DIR) + + find_path(Intl_INCLUDE_DIR + NAMES "libintl.h" + DOC "libintl include directory") + mark_as_advanced(Intl_INCLUDE_DIR) -find_library(Intl_LIBRARY ${Intl_LIBRARY_NAMES} NAMES_PER_DIR - DOC "intl library (potentially the C library)") -mark_as_advanced(Intl_LIBRARY) + find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR + DOC "libintl libraries (if not in the C library)") + mark_as_advanced(Intl_LIBRARY) +endif() # NOTE: glibc's libintl.h does not define LIBINTL_VERSION -if(Intl_INCLUDE_DIR AND NOT Intl_IS_BUILTIN) +if(Intl_INCLUDE_DIR AND EXISTS "${Intl_INCLUDE_DIR}/libintl.h") file(STRINGS ${Intl_INCLUDE_DIR}/libintl.h Intl_VERSION_DEFINE REGEX "LIBINTL_VERSION (.*)") if(Intl_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)") @@ -155,13 +158,20 @@ endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl FOUND_VAR Intl_FOUND - REQUIRED_VARS Intl_LIBRARY Intl_INCLUDE_DIR + REQUIRED_VARS ${_Intl_REQUIRED_VARS} VERSION_VAR Intl_VERSION FAIL_MESSAGE "Failed to find Gettext libintl") +unset(_Intl_REQUIRED_VARS) +unset(_Intl_IS_BUILT_IN_MSG) if(Intl_FOUND) - set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}") - set(Intl_LIBRARIES "${Intl_LIBRARY}") + if(Intl_IS_BUILT_IN) + set(Intl_INCLUDE_DIRS "") + set(Intl_LIBRARIES "") + else() + set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}") + set(Intl_LIBRARIES "${Intl_LIBRARY}") + endif() if(NOT TARGET Intl::Intl) add_library(Intl::Intl INTERFACE IMPORTED) set_target_properties(Intl::Intl PROPERTIES diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index 37869fb..e149f4c 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -21,7 +21,10 @@ Inclusion of this module defines the following variables: Destination for files of a given type. This value may be passed to the ``DESTINATION`` options of :command:`install` commands for the - corresponding file type. + corresponding file type. It should typically be a path relative to + the installation prefix so that it can be converted to an absolute + path in a relocatable way (see ``CMAKE_INSTALL_FULL_<dir>``). + However, an absolute path is also allowed. ``CMAKE_INSTALL_FULL_<dir>`` diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index 08bbc68..faaff7b 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -1349,15 +1349,21 @@ function(cpack_rpm_generate_package) continue() endif() - file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES false RELATIVE + file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES true RELATIVE "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}" "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/*") foreach(f_ IN LISTS files_for_move_) - get_filename_component(dir_path_ "${f_}" DIRECTORY) set(src_file_ "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/${f_}") + if(IS_DIRECTORY "${src_file_}") + file(MAKE_DIRECTORY "${WDIR}/${f_}") + continue() + endif() + + get_filename_component(dir_path_ "${f_}" DIRECTORY) + # check that we are not overriding an existing file that doesn't # match the file that we want to copy if(EXISTS "${src_file_}" AND EXISTS "${WDIR}/${f_}") @@ -1637,6 +1643,25 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ %description -n \@CPACK_RPM_PACKAGE_NAME\@ \@CPACK_RPM_PACKAGE_DESCRIPTION\@ +%post -n \@CPACK_RPM_PACKAGE_NAME\@ +\@RPM_SYMLINK_POSTINSTALL\@ +\@CPACK_RPM_SPEC_POSTINSTALL\@ + +%posttrans -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_POSTTRANS\@ + +%postun -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_POSTUNINSTALL\@ + +%pre -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_PREINSTALL\@ + +%pretrans -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_PRETRANS\@ + +%preun -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_PREUNINSTALL\@ + %files -n \@CPACK_RPM_PACKAGE_NAME\@ %defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@) \@CPACK_RPM_INSTALL_FILES\@ diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake index 6116ae1..50f0620 100644 --- a/Modules/Platform/Android-Initialize.cmake +++ b/Modules/Platform/Android-Initialize.cmake @@ -25,6 +25,56 @@ endif() set(CMAKE_BUILD_TYPE_INIT "RelWithDebInfo") +if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) + # Tell CMake not to search host sysroots for headers/libraries. + + # All paths added to CMAKE_SYSTEM_*_PATH below will be rerooted under + # CMAKE_FIND_ROOT_PATH. This is set because: + # 1. Users may structure their libraries in a way similar to NDK. When they do that, + # they can simply append another path to CMAKE_FIND_ROOT_PATH. + # 2. CMAKE_FIND_ROOT_PATH must be non-empty for CMAKE_FIND_ROOT_PATH_MODE_* == ONLY + # to be meaningful. https://github.com/android-ndk/ndk/issues/890 + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot") + + # Allow users to override these values in case they want more strict behaviors. + # For example, they may want to prevent the NDK's libz from being picked up so + # they can use their own. + # https://github.com/android-ndk/ndk/issues/517 + if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + endif() + + if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + endif() + + if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + endif() + + if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + endif() + + # Don't search paths in PATH environment variable. + if(NOT DEFINED CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH) + set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) + endif() + + # Allows CMake to find headers in the architecture-specific include directories. + set(CMAKE_LIBRARY_ARCHITECTURE "${CMAKE_ANDROID_ARCH_TRIPLE}") + + # Instructs CMake to search the correct API level for libraries. + # Besides the paths like <root>/<prefix>/lib/<arch>, cmake also searches <root>/<prefix>. + # So we can add the API level specific directory directly. + # https://github.com/android/ndk/issues/929 + list(PREPEND CMAKE_SYSTEM_PREFIX_PATH + "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/${CMAKE_SYSTEM_VERSION}" + ) + + list(APPEND CMAKE_SYSTEM_PROGRAM_PATH "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin") +endif() + # Skip sysroot selection if the NDK has a unified toolchain. if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) return() diff --git a/Modules/Platform/Android.cmake b/Modules/Platform/Android.cmake index e4b9a09..6944e32 100644 --- a/Modules/Platform/Android.cmake +++ b/Modules/Platform/Android.cmake @@ -35,56 +35,6 @@ if(CMAKE_SYSTEM_VERSION EQUAL 1) return() endif() -if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) - # Tell CMake not to search host sysroots for headers/libraries. - - # All paths added to CMAKE_SYSTEM_*_PATH below will be rerooted under - # CMAKE_FIND_ROOT_PATH. This is set because: - # 1. Users may structure their libraries in a way similar to NDK. When they do that, - # they can simply append another path to CMAKE_FIND_ROOT_PATH. - # 2. CMAKE_FIND_ROOT_PATH must be non-empty for CMAKE_FIND_ROOT_PATH_MODE_* == ONLY - # to be meaningful. https://github.com/android-ndk/ndk/issues/890 - list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot") - - # Allow users to override these values in case they want more strict behaviors. - # For example, they may want to prevent the NDK's libz from being picked up so - # they can use their own. - # https://github.com/android-ndk/ndk/issues/517 - if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - endif() - - if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - endif() - - if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - endif() - - if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - endif() - - # Don't search paths in PATH environment variable. - if(NOT DEFINED CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH) - set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) - endif() - - # Allows CMake to find headers in the architecture-specific include directories. - set(CMAKE_LIBRARY_ARCHITECTURE "${CMAKE_ANDROID_ARCH_TRIPLE}") - - # Instructs CMake to search the correct API level for libraries. - # Besides the paths like <root>/<prefix>/lib/<arch>, cmake also searches <root>/<prefix>. - # So we can add the API level specific directory directly. - # https://github.com/android/ndk/issues/929 - list(PREPEND CMAKE_SYSTEM_PREFIX_PATH - "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/${CMAKE_SYSTEM_VERSION}" - ) - - list(APPEND CMAKE_SYSTEM_PROGRAM_PATH "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin") -endif() - # Include the NDK hook. # It can be used by NDK to inject necessary fixes for an earlier cmake. if(CMAKE_ANDROID_NDK) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index b1e0576..c7d8346 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -38,7 +38,13 @@ Defines the following command for use with ``SWIG``: .. versionchanged:: 3.15 Alternate library name (set with the :prop_tgt:`OUTPUT_NAME` property, - for example) will be passed on to Python and CSharp wrapper libraries. + for example) will be passed on to ``Python`` and ``CSharp`` wrapper + libraries. + + .. versionchanged:: 3.21 + Generated library use standard naming conventions for ``CSharp`` language + when policy :policy:`CMP0122` is set to ``NEW``. Otherwise, the legacy + behavior is applied. .. note:: @@ -950,6 +956,17 @@ function(SWIG_ADD_LIBRARY name) endif () elseif (swig_lowercase_language STREQUAL "fortran") # Do *not* override the target's library prefix + elseif (swig_lowercase_language STREQUAL "csharp") + cmake_policy(GET CMP0122 csharp_naming_policy) + if (csharp_naming_policy STREQUAL "NEW") + # Do *not* override the target's library prefix + else() + if (NOT csharp_naming_policy) + cmake_policy(GET_WARNING CMP0122 _cmp0122_warning) + message(AUTHOR_WARNING "${_cmp0122_warning}\n") + endif() + set_target_properties (${target_name} PROPERTIES PREFIX "") + endif() else() # assume empty prefix because we expect the module to be dynamically loaded set_target_properties (${target_name} PROPERTIES PREFIX "") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 64077c4..9893e4b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210329) +set(CMake_VERSION_PATCH 20210401) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index c4bd7f1..1429c46 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -7,6 +7,8 @@ #include <sstream> #include <utility> +#include <cm/string_view> + #include "cmCPackComponentGroup.h" #include "cmCPackIFWCommon.h" #include "cmCPackIFWGenerator.h" @@ -30,44 +32,67 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default; cmCPackIFWPackage::DependenceStruct::DependenceStruct( const std::string& dependence) { - // Search compare section - size_t pos = std::string::npos; - if ((pos = dependence.find("<=")) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; - this->Compare.Value = dependence.substr(pos + 2); - } else if ((pos = dependence.find(">=")) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; - this->Compare.Value = dependence.substr(pos + 2); - } else if ((pos = dependence.find('<')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareLess; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('=')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareEqual; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('>')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareGreater; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('-')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareNone; - this->Compare.Value = dependence.substr(pos + 1); - } - size_t dashPos = dependence.find('-'); - if (dashPos != std::string::npos) { - pos = dashPos; - } - this->Name = dependence.substr(0, pos); + // Preferred format is name and version are separated by a colon (:), but + // note that this is only supported with QtIFW 3.1 or later. Backward + // compatibility allows a hyphen (-) as a separator instead, but names then + // cannot contain a hyphen. + size_t pos; + if ((pos = dependence.find(':')) == std::string::npos) { + pos = dependence.find('-'); + } + + if (pos != std::string::npos) { + this->Name = dependence.substr(0, pos); + ++pos; + if (pos == dependence.size()) { + // Nothing after the separator. Treat this as no version constraint. + return; + } + + const auto versionPart = + cm::string_view(dependence.data() + pos, dependence.size() - pos); + + if (cmHasLiteralPrefix(versionPart, "<=")) { + this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; + this->Compare.Value = std::string(versionPart.substr(2)); + } else if (cmHasLiteralPrefix(versionPart, ">=")) { + this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; + this->Compare.Value = std::string(versionPart.substr(2)); + } else if (cmHasPrefix(versionPart, '<')) { + this->Compare.Type = cmCPackIFWPackage::CompareLess; + this->Compare.Value = std::string(versionPart.substr(1)); + } else if (cmHasPrefix(versionPart, '=')) { + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = std::string(versionPart.substr(1)); + } else if (cmHasPrefix(versionPart, '>')) { + this->Compare.Type = cmCPackIFWPackage::CompareGreater; + this->Compare.Value = std::string(versionPart.substr(1)); + } else { + // We found no operator but a version specification is still expected to + // follow. The default behavior is to treat this the same as =. We + // explicitly record that as our type (it simplifies our logic a little + // and is also clearer). + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = std::string(versionPart); + } + } else { + this->Name = dependence; + } } std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const { - if (this->Compare.Type == cmCPackIFWPackage::CompareNone) { - return this->Name; - } - std::string result = this->Name; - - if (this->Compare.Type != cmCPackIFWPackage::CompareNone || - !this->Compare.Value.empty()) { + if (this->Name.find('-') != std::string::npos) { + // When a name contains a hyphen, we must use a colon after the name to + // prevent the hyphen from being parsed by QtIFW as the separator between + // the name and the version. Note that a colon is only supported with + // QtIFW 3.1 or later. + result += ":"; + } else if (this->Compare.Type != cmCPackIFWPackage::CompareNone || + !this->Compare.Value.empty()) { + // No hyphen in the name and we know a version part will follow. Use a + // hyphen as a separator since this works for all QtIFW versions. result += "-"; } @@ -609,6 +634,9 @@ void cmCPackIFWPackage::GeneratePackageFile() } // Dependencies + const bool hyphensInNamesUnsupported = this->Generator && + !this->Generator->FrameworkVersion.empty() && this->IsVersionLess("3.1"); + bool warnUnsupportedNames = false; std::set<DependenceStruct> compDepSet; for (DependenceStruct* ad : this->AlienDependencies) { compDepSet.insert(*ad); @@ -620,9 +648,13 @@ void cmCPackIFWPackage::GeneratePackageFile() if (!compDepSet.empty()) { std::ostringstream dependencies; auto it = compDepSet.begin(); + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << it->NameWithCompare(); ++it; while (it != compDepSet.end()) { + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << "," << it->NameWithCompare(); ++it; } @@ -638,15 +670,28 @@ void cmCPackIFWPackage::GeneratePackageFile() if (!compAutoDepSet.empty()) { std::ostringstream dependencies; auto it = compAutoDepSet.begin(); + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << it->NameWithCompare(); ++it; while (it != compAutoDepSet.end()) { + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << "," << it->NameWithCompare(); ++it; } xout.Element("AutoDependOn", dependencies.str()); } + if (warnUnsupportedNames) { + cmCPackIFWLogger( + WARNING, + "The dependencies for component \"" + << this->Name << "\" specify names that contain hyphens. " + << "This requires QtIFW 3.1 or later, but you are using version " + << this->Generator->FrameworkVersion << std::endl); + } + // Licenses (copy to meta dir) std::vector<std::string> licenses = this->Licenses; for (size_t i = 1; i < licenses.size(); i += 2) { diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 91818bb..cc756d7 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -21,32 +21,47 @@ cmCTestGenericHandler::cmCTestGenericHandler() cmCTestGenericHandler::~cmCTestGenericHandler() = default; -void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) +/* Modify the given `map`, setting key `op` to `value` if `value` + * is non-null, otherwise removing key `op` (if it exists). + */ +static void SetMapValue(cmCTestGenericHandler::t_StringToString& map, + const std::string& op, const char* value) { if (!value) { - auto remit = this->Options.find(op); - if (remit != this->Options.end()) { - this->Options.erase(remit); - } + map.erase(op); return; } - this->Options[op] = value; + map[op] = value; +} + +void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) +{ + SetMapValue(this->Options, op, value); } void cmCTestGenericHandler::SetPersistentOption(const std::string& op, const char* value) { this->SetOption(op, value); - if (!value) { - auto remit = this->PersistentOptions.find(op); - if (remit != this->PersistentOptions.end()) { - this->PersistentOptions.erase(remit); - } - return; + SetMapValue(this->PersistentOptions, op, value); +} + +void cmCTestGenericHandler::AddMultiOption(const std::string& op, + const std::string& value) +{ + if (!value.empty()) { + this->MultiOptions[op].emplace_back(value); } +} - this->PersistentOptions[op] = value; +void cmCTestGenericHandler::AddPersistentMultiOption(const std::string& op, + const std::string& value) +{ + if (!value.empty()) { + this->MultiOptions[op].emplace_back(value); + this->PersistentMultiOptions[op].emplace_back(value); + } } void cmCTestGenericHandler::Initialize() @@ -68,6 +83,17 @@ const char* cmCTestGenericHandler::GetOption(const std::string& op) return remit->second.c_str(); } +std::vector<std::string> cmCTestGenericHandler::GetMultiOption( + const std::string& optionName) const +{ + // Avoid inserting a key, which MultiOptions[op] would do. + auto remit = this->MultiOptions.find(optionName); + if (remit == this->MultiOptions.end()) { + return {}; + } + return remit->second; +} + bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part, const char* name, cmGeneratedFileStream& xofs) diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 89d7596..6f44545 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -72,11 +72,41 @@ public: virtual ~cmCTestGenericHandler(); using t_StringToString = std::map<std::string, std::string>; + using t_StringToMultiString = + std::map<std::string, std::vector<std::string>>; + /** + * Options collect a single value from flags; passing the + * flag multiple times on the command-line *overwrites* values, + * and only the last one specified counts. Set an option to + * nullptr to "unset" it. + * + * The value is stored as a string. The values set for single + * and multi-options (see below) live in different spaces, + * so calling a single-getter for a key that has only been set + * as a multi-value will return nullptr. + */ void SetPersistentOption(const std::string& op, const char* value); void SetOption(const std::string& op, const char* value); const char* GetOption(const std::string& op); + /** + * Multi-Options collect one or more values from flags; passing + * the flag multiple times on the command-line *adds* values, + * rather than overwriting the previous values. + * + * Adding an empty value does nothing. + * + * The value is stored as a vector of strings. The values set for single + * (see above) and multi-options live in different spaces, + * so calling a multi-getter for a key that has only been set + * as a single-value will return an empty vector. + */ + void AddPersistentMultiOption(const std::string& optionName, + const std::string& value); + void AddMultiOption(const std::string& optionName, const std::string& value); + std::vector<std::string> GetMultiOption(const std::string& op) const; + void SetCommand(cmCTestCommand* command) { this->Command = command; } void SetSubmitIndex(int idx) { this->SubmitIndex = idx; } @@ -100,6 +130,8 @@ protected: cmCTest* CTest; t_StringToString Options; t_StringToString PersistentOptions; + t_StringToMultiString MultiOptions; + t_StringToMultiString PersistentMultiOptions; t_StringToString LogFileNames; cmCTestCommand* Command; diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 4403733..886c263 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -73,11 +73,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() handler->SetOption("IncludeRegularExpression", this->Include.c_str()); } if (!this->ExcludeLabel.empty()) { - handler->SetOption("ExcludeLabelRegularExpression", - this->ExcludeLabel.c_str()); + handler->AddMultiOption("ExcludeLabelRegularExpression", + this->ExcludeLabel); } if (!this->IncludeLabel.empty()) { - handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str()); + handler->AddMultiOption("LabelRegularExpression", this->IncludeLabel); } if (!this->ExcludeFixture.empty()) { handler->SetOption("ExcludeFixtureRegularExpression", diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 42c4d5e..742e78a 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -287,8 +287,6 @@ cmCTestTestHandler::cmCTestTestHandler() { this->UseUnion = false; - this->UseIncludeLabelRegExpFlag = false; - this->UseExcludeLabelRegExpFlag = false; this->UseIncludeRegExpFlag = false; this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFirst = false; @@ -327,13 +325,11 @@ void cmCTestTestHandler::Initialize() this->TestsToRun.clear(); - this->UseIncludeLabelRegExpFlag = false; - this->UseExcludeLabelRegExpFlag = false; this->UseIncludeRegExpFlag = false; this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFirst = false; - this->IncludeLabelRegularExpression = ""; - this->ExcludeLabelRegularExpression = ""; + this->IncludeLabelRegularExpressions.clear(); + this->ExcludeLabelRegularExpressions.clear(); this->IncludeRegExp.clear(); this->ExcludeRegExp.clear(); this->ExcludeFixtureRegExp.clear(); @@ -479,6 +475,22 @@ int cmCTestTestHandler::ProcessHandler() return 0; } +/* Given a multi-option value `parts`, compile those parts into + * regular expressions in `expressions`. Skip empty values. + * Returns true if there were any expressions. + */ +static bool BuildLabelRE(const std::vector<std::string>& parts, + std::vector<cmsys::RegularExpression>& expressions) +{ + expressions.clear(); + for (const auto& p : parts) { + if (!p.empty()) { + expressions.emplace_back(p); + } + } + return !expressions.empty(); +} + bool cmCTestTestHandler::ProcessOptions() { // Update internal data structure from generic one @@ -519,18 +531,11 @@ bool cmCTestTestHandler::ProcessOptions() this->CTest->SetStopOnFailure(true); } - const char* val; - val = this->GetOption("LabelRegularExpression"); - if (val) { - this->UseIncludeLabelRegExpFlag = true; - this->IncludeLabelRegExp = val; - } - val = this->GetOption("ExcludeLabelRegularExpression"); - if (val) { - this->UseExcludeLabelRegExpFlag = true; - this->ExcludeLabelRegExp = val; - } - val = this->GetOption("IncludeRegularExpression"); + BuildLabelRE(this->GetMultiOption("LabelRegularExpression"), + this->IncludeLabelRegularExpressions); + BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), + this->ExcludeLabelRegularExpressions); + const char* val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -763,10 +768,40 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet); } +/** + * Check if the labels (from a test) match all the expressions. + * + * Each of the RE's must match at least one label + * (e.g. all of the REs must match **some** label, + * in order for the filter to apply to the test). + */ +static bool MatchLabelsAgainstFilterRE( + const std::vector<std::string>& labels, + const std::vector<cmsys::RegularExpression>& expressions) +{ + for (const auto& re : expressions) { + // check to see if the label regular expression matches + bool found = false; // assume it does not match + cmsys::RegularExpressionMatch match; + // loop over all labels and look for match + for (std::string const& l : labels) { + if (re.find(l.c_str(), match)) { + found = true; + break; + } + } + // if no match was found, exclude the test + if (!found) { + return false; + } + } + return true; +} + void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) { // if not using Labels to filter then return - if (!this->UseIncludeLabelRegExpFlag) { + if (this->IncludeLabelRegularExpressions.empty()) { return; } // if there are no labels and we are filtering by labels @@ -775,16 +810,9 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) it.IsInBasedOnREOptions = false; return; } - // check to see if the label regular expression matches - bool found = false; // assume it does not match - // loop over all labels and look for match - for (std::string const& l : it.Labels) { - if (this->IncludeLabelRegularExpression.find(l)) { - found = true; - } - } // if no match was found, exclude the test - if (!found) { + if (!MatchLabelsAgainstFilterRE(it.Labels, + this->IncludeLabelRegularExpressions)) { it.IsInBasedOnREOptions = false; } } @@ -792,7 +820,7 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) { // if not using Labels to filter then return - if (!this->UseExcludeLabelRegExpFlag) { + if (this->ExcludeLabelRegularExpressions.empty()) { return; } // if there are no labels and we are excluding by labels @@ -800,16 +828,9 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) if (it.Labels.empty()) { return; } - // check to see if the label regular expression matches - bool found = false; // assume it does not match - // loop over all labels and look for match - for (std::string const& l : it.Labels) { - if (this->ExcludeLabelRegularExpression.find(l)) { - found = true; - } - } // if match was found, exclude the test - if (found) { + if (MatchLabelsAgainstFilterRE(it.Labels, + this->ExcludeLabelRegularExpressions)) { it.IsInBasedOnREOptions = false; } } @@ -1704,12 +1725,6 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty( bool cmCTestTestHandler::GetListOfTests() { - if (!this->IncludeLabelRegExp.empty()) { - this->IncludeLabelRegularExpression.compile(this->IncludeLabelRegExp); - } - if (!this->ExcludeLabelRegExp.empty()) { - this->ExcludeLabelRegularExpression.compile(this->ExcludeLabelRegExp); - } if (!this->IncludeRegExp.empty()) { this->IncludeTestsRegularExpression.compile(this->IncludeRegExp); } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index aa29eeb..6fa18a9 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -320,20 +320,16 @@ private: std::vector<int> TestsToRun; - bool UseIncludeLabelRegExpFlag; - bool UseExcludeLabelRegExpFlag; bool UseIncludeRegExpFlag; bool UseExcludeRegExpFlag; bool UseExcludeRegExpFirst; - std::string IncludeLabelRegExp; - std::string ExcludeLabelRegExp; std::string IncludeRegExp; std::string ExcludeRegExp; std::string ExcludeFixtureRegExp; std::string ExcludeFixtureSetupRegExp; std::string ExcludeFixtureCleanupRegExp; - cmsys::RegularExpression IncludeLabelRegularExpression; - cmsys::RegularExpression ExcludeLabelRegularExpression; + std::vector<cmsys::RegularExpression> IncludeLabelRegularExpressions; + std::vector<cmsys::RegularExpression> ExcludeLabelRegularExpressions; cmsys::RegularExpression IncludeTestsRegularExpression; cmsys::RegularExpression ExcludeTestsRegularExpression; diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index fbe9fe5..d44dfb3 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -11,6 +11,8 @@ #include <cm/string_view> +#include "cmsys/RegularExpression.hxx" + #include "cmCMakePresetsFileInternal.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -561,6 +563,24 @@ bool cmCMakePresetsFileInternal::InListCondition::Evaluate( return true; } +bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate( + const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const +{ + std::string str = this->String; + CHECK_EXPAND(out, str, expanders, version); + std::string regexStr = this->Regex; + CHECK_EXPAND(out, regexStr, expanders, version); + + cmsys::RegularExpression regex; + if (!regex.compile(regexStr)) { + return false; + } + + out = regex.find(str); + return true; +} + bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate( const std::vector<MacroExpander>& expanders, int version, cm::optional<bool>& out) const diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h index ffb6ce9..3269276 100644 --- a/Source/cmCMakePresetsFileInternal.h +++ b/Source/cmCMakePresetsFileInternal.h @@ -81,6 +81,16 @@ public: std::vector<std::string> List; }; +class MatchesCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const override; + + std::string String; + std::string Regex; +}; + class AnyAllOfCondition : public cmCMakePresetsFile::Condition { public: diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx index e26e7b4..403fac6 100644 --- a/Source/cmCMakePresetsFileReadJSON.cxx +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -93,6 +93,16 @@ auto const InListConditionHelper = .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List, ConditionStringListHelper, true); +auto const MatchesConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::MatchesCondition, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("string"_s, &cmCMakePresetsFileInternal::MatchesCondition::String, + ConditionStringHelper, true) + .Bind("regex"_s, &cmCMakePresetsFileInternal::MatchesCondition::Regex, + ConditionStringHelper, true); + ReadFileResult SubConditionHelper( std::unique_ptr<cmCMakePresetsFile::Condition>& out, const Json::Value* value); @@ -177,6 +187,16 @@ ReadFileResult ConditionHelper( return ReadFileResult::READ_OK; } + if (type == "matches" || type == "notMatches") { + auto c = cm::make_unique<cmCMakePresetsFileInternal::MatchesCondition>(); + CHECK_OK(MatchesConditionHelper(*c, value)); + out = std::move(c); + if (type == "notMatches") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + if (type == "anyOf" || type == "allOf") { auto c = cm::make_unique<cmCMakePresetsFileInternal::AnyAllOfCondition>(); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 4228d30..0dfd1bd 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2108,17 +2108,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } else if (this->CheckArgument(arg, "-L"_s, "--label-regex") && i < args.size() - 1) { i++; - this->GetTestHandler()->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); - this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); + this->GetTestHandler()->AddPersistentMultiOption("LabelRegularExpression", + args[i]); + this->GetMemCheckHandler()->AddPersistentMultiOption( + "LabelRegularExpression", args[i]); } else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") && i < args.size() - 1) { i++; - this->GetTestHandler()->SetPersistentOption( - "ExcludeLabelRegularExpression", args[i].c_str()); - this->GetMemCheckHandler()->SetPersistentOption( - "ExcludeLabelRegularExpression", args[i].c_str()); + this->GetTestHandler()->AddPersistentMultiOption( + "ExcludeLabelRegularExpression", args[i]); + this->GetMemCheckHandler()->AddPersistentMultiOption( + "ExcludeLabelRegularExpression", args[i]); } else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") && @@ -2268,6 +2268,15 @@ void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value, } } +void cmCTest::AddPersistentMultiOptionIfNotEmpty(const std::string& value, + const std::string& optionName) +{ + if (!value.empty()) { + this->GetTestHandler()->AddPersistentMultiOption(optionName, value); + this->GetMemCheckHandler()->AddPersistentMultiOption(optionName, value); + } +} + bool cmCTest::SetArgsFromPreset(const std::string& presetName, bool listPresets) { @@ -2419,7 +2428,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (expandedPreset->Filter->Include) { this->SetPersistentOptionIfNotEmpty( expandedPreset->Filter->Include->Name, "IncludeRegularExpression"); - this->SetPersistentOptionIfNotEmpty( + this->AddPersistentMultiOptionIfNotEmpty( expandedPreset->Filter->Include->Label, "LabelRegularExpression"); if (expandedPreset->Filter->Include->Index) { @@ -2452,7 +2461,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (expandedPreset->Filter->Exclude) { this->SetPersistentOptionIfNotEmpty( expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression"); - this->SetPersistentOptionIfNotEmpty( + this->AddPersistentMultiOptionIfNotEmpty( expandedPreset->Filter->Exclude->Label, "ExcludeLabelRegularExpression"); diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 4669a1c..392eb1c 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -463,6 +463,8 @@ public: private: void SetPersistentOptionIfNotEmpty(const std::string& value, const std::string& optionName); + void AddPersistentMultiOptionIfNotEmpty(const std::string& value, + const std::string& optionName); int GenerateNotesFile(const std::string& files); diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index 6b75da0..b14cfc2 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -76,8 +76,9 @@ struct cmCommandLineArgument } else if (this->Type == Values::One || this->Type == Values::ZeroOrOne) { if (input.size() == this->Name.size()) { - ++index; - if (index >= allArgs.size() || allArgs[index][0] == '-') { + auto nextValueIndex = index + 1; + if (nextValueIndex >= allArgs.size() || + allArgs[nextValueIndex][0] == '-') { if (this->Type == Values::ZeroOrOne) { parseState = this->StoreCall(std::string{}, std::forward<CallState>(state)...) @@ -87,10 +88,11 @@ struct cmCommandLineArgument parseState = ParseMode::ValueError; } } else { - parseState = - this->StoreCall(allArgs[index], std::forward<CallState>(state)...) + parseState = this->StoreCall(allArgs[nextValueIndex], + std::forward<CallState>(state)...) ? ParseMode::Valid : ParseMode::Invalid; + index = nextValueIndex; } } else { // parse the string to get the value @@ -137,7 +139,8 @@ struct cmCommandLineArgument } else if (this->Type == Values::OneOrMore) { if (input.size() == this->Name.size()) { auto nextValueIndex = index + 1; - if (nextValueIndex >= allArgs.size() || allArgs[index + 1][0] == '-') { + if (nextValueIndex >= allArgs.size() || + allArgs[nextValueIndex][0] == '-') { parseState = ParseMode::ValueError; } else { std::string buffer = allArgs[nextValueIndex++]; @@ -149,6 +152,7 @@ struct cmCommandLineArgument this->StoreCall(buffer, std::forward<CallState>(state)...) ? ParseMode::Valid : ParseMode::Invalid; + index = (nextValueIndex - 1); } } } diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index edd261d..12b2925 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -165,7 +165,7 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, return false; } - mode_t permisiions = 0; + mode_t permissions = 0; if (filePermissions) { if (filePermissionOptions.empty()) { @@ -175,7 +175,7 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, std::vector<std::string> invalidOptions; for (auto const& e : filePermissionOptions) { - if (!cmFSPermissions::stringToModeT(e, permisiions)) { + if (!cmFSPermissions::stringToModeT(e, permissions)) { invalidOptions.push_back(e); } } @@ -197,14 +197,14 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, } if (noSourcePermissions) { - permisiions |= cmFSPermissions::mode_owner_read; - permisiions |= cmFSPermissions::mode_owner_write; - permisiions |= cmFSPermissions::mode_group_read; - permisiions |= cmFSPermissions::mode_world_read; + permissions |= cmFSPermissions::mode_owner_read; + permissions |= cmFSPermissions::mode_owner_write; + permissions |= cmFSPermissions::mode_group_read; + permissions |= cmFSPermissions::mode_world_read; } if (!status.GetMakefile().ConfigureFile(inputFile, outputFile, copyOnly, - atOnly, escapeQuotes, permisiions, + atOnly, escapeQuotes, permissions, newLineStyle)) { status.SetError("Problem configuring file"); return false; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index c6b6184..cac60e1 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -3,9 +3,10 @@ #include "cmExportTryCompileFileGenerator.h" #include <map> -#include <memory> #include <utility> +#include <cm/memory> + #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" @@ -66,7 +67,15 @@ std::string cmExportTryCompileFileGenerator::FindTargets( cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr); + std::unique_ptr<cmGeneratorExpressionDAGChecker> parentDagChecker; + if (propName == "INTERFACE_LINK_OPTIONS") { + // To please constraint checks of DAGChecker, this property must have + // LINK_OPTIONS property as parent + parentDagChecker = cm::make_unique<cmGeneratorExpressionDAGChecker>( + tgt, "LINK_OPTIONS", nullptr, nullptr); + } + cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, + parentDagChecker.get()); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*prop); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1c73d0d..a06ed48 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2577,18 +2577,18 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, } } - mode_t permisiions = 0; + mode_t permissions = 0; if (arguments.NoSourcePermissions) { - permisiions |= cmFSPermissions::mode_owner_read; - permisiions |= cmFSPermissions::mode_owner_write; - permisiions |= cmFSPermissions::mode_group_read; - permisiions |= cmFSPermissions::mode_world_read; + permissions |= cmFSPermissions::mode_owner_read; + permissions |= cmFSPermissions::mode_owner_write; + permissions |= cmFSPermissions::mode_group_read; + permissions |= cmFSPermissions::mode_world_read; } if (!arguments.FilePermissions.empty()) { std::vector<std::string> invalidOptions; for (auto const& e : arguments.FilePermissions) { - if (!cmFSPermissions::stringToModeT(e, permisiions)) { + if (!cmFSPermissions::stringToModeT(e, permissions)) { invalidOptions.push_back(e); } } @@ -2610,7 +2610,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, AddEvaluationFile(input, arguments.Target, arguments.Output, arguments.Condition, inputIsContent, - newLineStyle.GetCharacters(), permisiions, status); + newLineStyle.GetCharacters(), permissions, status); return true; } diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx index c782bcd..afa8e9b 100644 --- a/Source/cmGccDepfileLexerHelper.cxx +++ b/Source/cmGccDepfileLexerHelper.cxx @@ -12,6 +12,8 @@ #include "LexerParser/cmGccDepfileLexer.h" #ifdef _WIN32 +# include <cctype> + # include "cmsys/Encoding.h" #endif @@ -123,11 +125,21 @@ void cmGccDepfileLexerHelper::sanitizeContent() if (it->rules.empty()) { it = this->Content.erase(it); } else { - // Remove empty paths + // Remove empty paths and normalize windows paths for (auto pit = it->paths.begin(); pit != it->paths.end();) { if (pit->empty()) { pit = it->paths.erase(pit); } else { +#if defined(_WIN32) + // Unescape the colon following the drive letter. + // Some versions of GNU compilers can escape this character. + // c\:\path must be transformed to c:\path + if (pit->size() >= 3 && std::toupper((*pit)[0]) >= 'A' && + std::toupper((*pit)[0]) <= 'Z' && (*pit)[1] == '\\' && + (*pit)[2] == ':') { + pit->erase(1, 1); + } +#endif ++pit; } } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d3c9959..365f8b8 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3655,13 +3655,58 @@ std::vector<BT<std::string>> wrapOptions( return result; } - if (wrapperFlag.empty() || cmHasLiteralPrefix(options.front(), "LINKER:")) { - // nothing specified or LINKER wrapper, insert elements as is + if (wrapperFlag.empty()) { + // nothing specified, insert elements as is result.reserve(options.size()); for (std::string& o : options) { result.emplace_back(std::move(o), bt); } - } else { + return result; + } + + for (std::vector<std::string>::size_type index = 0; index < options.size(); + index++) { + if (cmHasLiteralPrefix(options[index], "LINKER:")) { + // LINKER wrapper specified, insert elements as is + result.emplace_back(std::move(options[index]), bt); + continue; + } + if (cmHasLiteralPrefix(options[index], "-Wl,")) { + // replace option by LINKER wrapper + result.emplace_back(options[index].replace(0, 4, "LINKER:"), bt); + continue; + } + if (cmHasLiteralPrefix(options[index], "-Xlinker=")) { + // replace option by LINKER wrapper + result.emplace_back(options[index].replace(0, 9, "LINKER:"), bt); + continue; + } + if (options[index] == "-Xlinker") { + // replace option by LINKER wrapper + if (index + 1 < options.size()) { + result.emplace_back("LINKER:" + options[++index], bt); + } else { + result.emplace_back(std::move(options[index]), bt); + } + continue; + } + + // collect all options which must be transformed + std::vector<std::string> opts; + while (index < options.size()) { + if (!cmHasLiteralPrefix(options[index], "LINKER:") && + !cmHasLiteralPrefix(options[index], "-Wl,") && + !cmHasLiteralPrefix(options[index], "-Xlinker")) { + opts.emplace_back(std::move(options[index++])); + } else { + --index; + break; + } + } + if (opts.empty()) { + continue; + } + if (!wrapperSep.empty()) { if (concatFlagAndArgs) { // insert flag elements except last one @@ -3670,24 +3715,23 @@ std::vector<BT<std::string>> wrapOptions( } // concatenate last flag element and all list values // in one option - result.emplace_back(wrapperFlag.back() + cmJoin(options, wrapperSep), - bt); + result.emplace_back(wrapperFlag.back() + cmJoin(opts, wrapperSep), bt); } else { for (std::string const& i : wrapperFlag) { result.emplace_back(i, bt); } // concatenate all list values in one option - result.emplace_back(cmJoin(options, wrapperSep), bt); + result.emplace_back(cmJoin(opts, wrapperSep), bt); } } else { // prefix each element of list with wrapper if (concatFlagAndArgs) { - std::transform(options.begin(), options.end(), options.begin(), + std::transform(opts.begin(), opts.end(), opts.begin(), [&wrapperFlag](std::string const& o) -> std::string { return wrapperFlag.back() + o; }); } - for (std::string& o : options) { + for (std::string& o : opts) { for (auto i = wrapperFlag.begin(), e = concatFlagAndArgs ? wrapperFlag.end() - 1 : wrapperFlag.end(); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index f2575c9..03d1697 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -585,6 +585,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( auto ccgs = this->MakeCustomCommandGenerators(*cc, fileConfig); for (cmCustomCommandGenerator const& ccg : ccgs) { + if (ccg.GetOutputs().empty() && ccg.GetByproducts().empty()) { + // Generator expressions evaluate to no output for this config. + continue; + } + cmNinjaDeps orderOnlyDeps; // A custom command may appear on multiple targets. However, some build diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 9295a3f..d546b6e 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -362,7 +362,11 @@ class cmMakefile; cmPolicies::WARN) \ SELECT(POLICY, CMP0121, \ "The list() command now validates parsing of index arguments.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0122, \ + "UseSWIG use standard library name conventions for csharp language.", 3, \ + 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 450a0cd..6528687 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1494,15 +1494,15 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() headers.reserve(this->AutogenTarget.Headers.size()); for (auto const& pair : this->AutogenTarget.Headers) { MUFile const* const muf = pair.second.get(); - if (muf->Generated && !this->CMP0071Accept) { - continue; - } if (muf->SkipMoc) { moc_skip.insert(muf->FullPath); } if (muf->SkipUic) { uic_skip.insert(muf->FullPath); } + if (muf->Generated && !this->CMP0071Accept) { + continue; + } if (muf->MocIt || muf->UicIt) { headers.emplace_back(muf); } diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 02b32dd..c32c965 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -2248,6 +2248,13 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process() std::for_each(this->MocEval().SourceMappings.begin(), this->MocEval().SourceMappings.end(), processMappingEntry); + // Remove SKIP_AUTOMOC files + dependencies.erase(std::remove_if(dependencies.begin(), dependencies.end(), + [this](const std::string& dep) { + return this->MocConst().skipped(dep); + }), + dependencies.end()); + // Remove duplicates to make the depfile smaller std::sort(dependencies.begin(), dependencies.end()); dependencies.erase(std::unique(dependencies.begin(), dependencies.end()), diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 3c331d3..a4b85ae 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -55,8 +55,9 @@ static const char* cmDocumentationOptions[][2] = { "format of the test information and can be 'human' for the current text " "format or 'json-v1' for json format. Defaults to 'human'." }, { "-L <regex>, --label-regex <regex>", - "Run tests with labels matching " - "regular expression." }, + "Run tests with labels matching regular expression. " + "With multiple -L, run tests where each " + "regular expression matches at least one label." }, { "-R <regex>, --tests-regex <regex>", "Run tests matching regular " "expression." }, @@ -64,8 +65,9 @@ static const char* cmDocumentationOptions[][2] = { "Exclude tests matching regular " "expression." }, { "-LE <regex>, --label-exclude <regex>", - "Exclude tests with labels " - "matching regular expression." }, + "Exclude tests with labels matching regular expression. " + "With multiple -LE, exclude tests where each " + "regular expression matches at least one label." }, { "-FA <regex>, --fixture-exclude-any <regex>", "Do not automatically " "add any tests for " diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index cf04799..4d974a8 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -3926,7 +3926,7 @@ bool SystemTools::FileIsFullPath(const char* in_name) bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) { -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) // On Windows, the name must be at least two characters long. if (len < 2) { return false; diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 4d1b46c..9409d1b 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -10,7 +10,7 @@ #endif /* Configure support for this platform. */ -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) # define KWSYS_TERMINAL_SUPPORT_CONSOLE #endif #if !defined(_WIN32) diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 6bbbe7d..52959e6 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -7,6 +7,7 @@ macro(AddCMakeTest TestName PreArgs) add_test(NAME CMake.${TestName} COMMAND ${CMAKE_EXECUTABLE} ${PreArgs} -P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN}) + set_tests_properties("CMake.${TestName}" PROPERTIES LABELS "CMake;command") endmacro() diff --git a/Tests/CTestTestLabelRegExp/test.cmake.in b/Tests/CTestTestLabelRegExp/test.cmake.in index 5c0c9d7..dd40c3b 100644 --- a/Tests/CTestTestLabelRegExp/test.cmake.in +++ b/Tests/CTestTestLabelRegExp/test.cmake.in @@ -27,11 +27,15 @@ expect_test_list("test1.*test3.*Total Tests: 2" --label-regex foo) expect_test_list("test2.*test3.*Total Tests: 2" --label-regex bar) expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-regex foo|bar) expect_test_list("Total Tests: 0" --label-regex baz) +expect_test_list("Total Tests: 0" --label-regex foo --label-regex baz) +expect_test_list("test3.*Total Tests: 1" --label-regex foo --label-regex bar) expect_test_list("test2.*Total Tests: 1" --label-exclude foo) expect_test_list("test1.*Total Tests: 1" --label-exclude bar) expect_test_list("Total Tests: 0" --label-exclude foo|bar) expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude baz) +expect_test_list("test1.*test2.*Total Tests: 2" --label-exclude foo --label-exclude bar) +expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude foo --label-exclude baz) expect_test_list("test1.*Total Tests: 1" --label-regex foo --label-exclude bar) expect_test_list("test2.*Total Tests: 1" --label-regex bar --label-exclude foo) diff --git a/Tests/QtAutogen/TestMacros.cmake b/Tests/QtAutogen/TestMacros.cmake index 1024996..9dcf31f 100644 --- a/Tests/QtAutogen/TestMacros.cmake +++ b/Tests/QtAutogen/TestMacros.cmake @@ -43,6 +43,7 @@ macro(ADD_AUTOGEN_TEST NAME) --build-options ${build_options} ${Autogen_BUILD_OPTIONS} ${_TestCommand} ) + set_tests_properties("${_QtXAutogen}.${NAME}" PROPERTIES LABELS "Qt${QT_TEST_VERSION}") list(APPEND TEST_BUILD_DIRS "${_BuildDir}") unset(_TestCommand) unset(_QtXAutogen) diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake index d1edd72..ab5686a 100644 --- a/Tests/QtAutogen/Tests.cmake +++ b/Tests/QtAutogen/Tests.cmake @@ -36,7 +36,9 @@ ADD_AUTOGEN_TEST(UnityMocSource) if(QT_TEST_ALLOW_QT_MACROS) ADD_AUTOGEN_TEST(MocCMP0071) + set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0071" APPEND PROPERTY LABELS "policy") ADD_AUTOGEN_TEST(MocCMP0100) + set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0100" APPEND PROPERTY LABELS "policy") ADD_AUTOGEN_TEST(MocInclude) ADD_AUTOGEN_TEST(MocIncludeSymlink) ADD_AUTOGEN_TEST(MocSkipSource) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 9a6a103..5f5a28f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -29,6 +29,10 @@ macro(add_RunCMake_test test) ${TEST_ARGS} -P "${CMAKE_CURRENT_SOURCE_DIR}/${Test_Dir}/RunCMakeTest.cmake" ) + set_tests_properties("RunCMake.${test}" PROPERTIES LABELS "CMake;run") + if(${test} MATCHES ^CMP) + set_property(TEST "RunCMake.${test}" APPEND PROPERTY LABELS "policy") + endif() endmacro() function(add_RunCMake_test_group test types) @@ -142,6 +146,9 @@ endif() if(CMAKE_GENERATOR MATCHES "Make") add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU}) endif() +if(CMake_TEST_Qt5) + find_package(Qt5Widgets QUIET NO_MODULE) +endif() if(CMAKE_GENERATOR MATCHES "Ninja") set(Ninja_ARGS -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} @@ -152,6 +159,9 @@ if(CMAKE_GENERATOR MATCHES "Ninja") endif() if(CMake_TEST_Qt5 AND Qt5Core_FOUND) list(APPEND Ninja_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION}) + if(Qt5Widgets_FOUND) + list(APPEND Ninja_ARGS -DQt5Widgets_DIR=${Qt5Widgets_DIR}) + endif() endif() add_RunCMake_test(Ninja) set(NinjaMultiConfig_ARGS @@ -191,9 +201,6 @@ if(CMake_TEST_APPLE_SILICON) add_RunCMake_test(AppleSilicon) endif() set(autogen_with_qt5 FALSE) -if(CMake_TEST_Qt5) - find_package(Qt5Widgets QUIET NO_MODULE) -endif() if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND) set(autogen_with_qt5 TRUE) endif () diff --git a/Tests/RunCMake/CMakePresets/Conditions.json.in b/Tests/RunCMake/CMakePresets/Conditions.json.in index 9a01e2f..9c0c6bd 100644 --- a/Tests/RunCMake/CMakePresets/Conditions.json.in +++ b/Tests/RunCMake/CMakePresets/Conditions.json.in @@ -181,6 +181,63 @@ } }, { + "name": "MatchesTrue", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "aaa", + "regex": "^a*$" + } + }, + { + "name": "MatchesFalse", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "aab", + "regex": "^a*$" + } + }, + { + "name": "MatchesMacroString", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "${presetName}", + "regex": "^Matches" + } + }, + { + "name": "MatchesMacroRegex", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "stuff", + "regex": "$env{CONDITION_REGEX}" + }, + "environment": { + "CONDITION_REGEX": "^stuf*$" + } + }, + { + "name": "NotMatchesTrue", + "inherits": "Base", + "condition": { + "type": "notMatches", + "string": "aab", + "regex": "^a*$" + } + }, + { + "name": "NotMatchesFalse", + "inherits": "Base", + "condition": { + "type": "notMatches", + "string": "aaa", + "regex": "^a*$" + } + }, + { "name": "AnyOfTrue1", "inherits": "Base", "condition": { diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt new file mode 100644 index 0000000..5b500e4 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/InvalidRegex: Invalid macro expansion$ diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex.json.in b/Tests/RunCMake/CMakePresets/InvalidRegex.json.in new file mode 100644 index 0000000..69114d2 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/InvalidRegex.json.in @@ -0,0 +1,15 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "InvalidRegex", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@", + "condition": { + "type": "matches", + "string": "a", + "regex": "+" + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt index 19f91d4..91e0017 100644 --- a/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt +++ b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt @@ -12,6 +12,10 @@ Available configure presets: "InListMacroList" "InListShortCircuit" "NotInListTrue" + "MatchesTrue" + "MatchesMacroString" + "MatchesMacroRegex" + "NotMatchesTrue" "AnyOfTrue1" "AnyOfTrue2" "AnyOfShortCircuit" diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 22425b2..9523430 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -117,6 +117,7 @@ run_cmake_presets(NoSuchMacro) run_cmake_presets(EnvCycle) run_cmake_presets(EmptyEnv) run_cmake_presets(EmptyPenv) +run_cmake_presets(InvalidRegex) set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) run_cmake_presets(ConditionFuture) run_cmake_presets(SubConditionNull) diff --git a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake index 3416205..e95cd15 100644 --- a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake +++ b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake @@ -13,4 +13,11 @@ function(get_test_prerequirements found_var config_file) "\nset(RPMBUILD_EXECUTABLE \"${RPMBUILD_EXECUTABLE}\")") set(${found_var} true PARENT_SCOPE) endif() + + # optional tool for some tests + find_program(OBJDUMP_EXECUTABLE objdump) + if(OBJDUMP_EXECUTABLE) + file(APPEND "${config_file}" + "\nset(OBJDUMP_EXECUTABLE \"${OBJDUMP_EXECUTABLE}\")") + endif() endfunction() diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 15bfb60..48b9c1d 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -16,7 +16,7 @@ run_cpack_test(VERSION "RPM.VERSION;DEB.VERSION" false "MONOLITHIC;COMPONENT") run_cpack_test(EXTRA "DEB.EXTRA" false "COMPONENT") run_cpack_test_subtests(GENERATE_SHLIBS "soversion_not_zero;soversion_zero" "DEB.GENERATE_SHLIBS" true "COMPONENT") run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB.GENERATE_SHLIBS_LDCONFIG" true "COMPONENT") -run_cpack_test(INSTALL_SCRIPTS "RPM.INSTALL_SCRIPTS" false "COMPONENT") +run_cpack_test_subtests(INSTALL_SCRIPTS "default;single_debug_info" "RPM.INSTALL_SCRIPTS" false "COMPONENT") run_cpack_test(LONG_FILENAMES "DEB.LONG_FILENAMES" false "MONOLITHIC") run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM.MAIN_COMPONENT" false "COMPONENT") run_cpack_test(MINIMAL "RPM.MINIMAL;DEB.MINIMAL;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake index de38df9..29e36a3 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake @@ -1,5 +1,10 @@ +if(RunCMake_SUBTEST_SUFFIX STREQUAL "single_debug_info") + set(EXPECTED_FILE_1 "install_scripts-0.1.1-1.*.rpm") +else() + set(EXPECTED_FILE_1_COMPONENT "foo") +endif() + set(EXPECTED_FILES_COUNT "2") -set(EXPECTED_FILE_1_COMPONENT "foo") set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_COMPONENT "bar") set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake new file mode 100644 index 0000000..c5d20cc --- /dev/null +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake @@ -0,0 +1,11 @@ +function(get_test_prerequirements found_var config_file) + if(SUBTEST_SUFFIX STREQUAL "single_debug_info") + include(${config_file}) + + if(OBJDUMP_EXECUTABLE) + set(${found_var} true PARENT_SCOPE) + endif() + else() + set(${found_var} true PARENT_SCOPE) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake index c200fa5..6877c57 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake @@ -24,6 +24,12 @@ if(GENERATOR_TYPE STREQUAL "RPM") "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh") set(CPACK_RPM_foo_POST_TRANS_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh") + + if(RunCMake_SUBTEST_SUFFIX STREQUAL "single_debug_info") + set(CPACK_RPM_MAIN_COMPONENT "foo") + set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) + set(CPACK_RPM_FOO_FILE_NAME "RPM-DEFAULT") + endif() endif() set(CMAKE_BUILD_WITH_INSTALL_RPATH 1) diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake index 936e4ed..1dc7084 100644 --- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake @@ -9,7 +9,7 @@ if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm") set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm") - set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") + set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so;/empty_dir") set(EXPECTED_FILE_4_COMPONENT "debuginfo") set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*") diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake index 60e9038..064539e 100644 --- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake +++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake @@ -30,6 +30,9 @@ if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo") install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers) install(TARGETS test_lib DESTINATION bas COMPONENT libs) + + # test that we correctly handle empty dir in non main component + install(DIRECTORY DESTINATION empty_dir COMPONENT libs) elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo") set(CPACK_COMPONENTS_ALL applications) diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--invalid-target-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--invalid-target-result.txt new file mode 100644 index 0000000..3beecb0 --- /dev/null +++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--invalid-target-result.txt @@ -0,0 +1 @@ +(1|2) diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--invalid-target-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--invalid-target-stderr.txt new file mode 100644 index 0000000..ee4bcc0 --- /dev/null +++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--invalid-target-stderr.txt @@ -0,0 +1 @@ +.*(ninja: error: unknown target 'invalid-target'|No rule to make target [`']invalid-target').* diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index a2b2044..c497472 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -212,6 +212,10 @@ function(run_BuildDir) ${CMAKE_COMMAND} --build BuildDir-build -j) run_cmake_command(BuildDir--build-jobs-no-number-trailing--target ${CMAKE_COMMAND} -E chdir .. ${CMAKE_COMMAND} --build BuildDir-build -j --target CustomTarget) + if(RunCMake_GENERATOR MATCHES "Unix Makefiles" OR RunCMake_GENERATOR MATCHES "Ninja") + run_cmake_command(BuildDir--build-jobs-no-number-trailing--invalid-target ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build BuildDir-build -j --target invalid-target) + endif() run_cmake_command(BuildDir--build--parallel-no-number ${CMAKE_COMMAND} -E chdir .. ${CMAKE_COMMAND} --build BuildDir-build --parallel) run_cmake_command(BuildDir--build--parallel-no-number-trailing--target ${CMAKE_COMMAND} -E chdir .. diff --git a/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake index 8b30f96..31494d5 100644 --- a/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake +++ b/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake @@ -2,7 +2,7 @@ if(NOT EXISTS "${generatedFile}") message(SEND_ERROR "Missing generated file:\n ${generatedFile}") endif() -if (UNIX) +if (CMAKE_HOST_UNIX) find_program(STAT_EXECUTABLE NAMES stat) if(NOT STAT_EXECUTABLE) return() diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake new file mode 100644 index 0000000..281f8aa --- /dev/null +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake @@ -0,0 +1,9 @@ + +enable_language(C) + +add_library(demo INTERFACE IMPORTED) +set_property(TARGET demo PROPERTY INTERFACE_LINK_OPTIONS "$<DEVICE_LINK:>") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) +try_compile(result "${CMAKE_CURRENT_BINARY_DIR}/tc" "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" + LINK_LIBRARIES demo) diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake index 1e44601..80633e2 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake @@ -12,6 +12,7 @@ run_cmake(DEVICE_LINK-target_compile_options) run_cmake(DEVICE_LINK-target_include_directories) run_cmake(DEVICE_LINK-target_link_libraries) run_cmake(DEVICE_LINK-target_link_directories) +run_cmake(DEVICE_LINK-try_compile) if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)") run_cmake(DEVICE_LINK-link_depends) endif() diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake b/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake new file mode 100644 index 0000000..f221ff1 --- /dev/null +++ b/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake @@ -0,0 +1,9 @@ + +enable_language(C) + +add_library(demo INTERFACE IMPORTED) +set_property(TARGET demo PROPERTY INTERFACE_LINK_OPTIONS "$<HOST_LINK:>") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) +try_compile(result "${CMAKE_CURRENT_BINARY_DIR}/tc" "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" + LINK_LIBRARIES demo) diff --git a/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake index 329a7c6..9e3eeec 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake @@ -12,6 +12,7 @@ run_cmake(HOST_LINK-target_compile_options) run_cmake(HOST_LINK-target_include_directories) run_cmake(HOST_LINK-target_link_libraries) run_cmake(HOST_LINK-target_link_directories) +run_cmake(HOST_LINK-try_compile) if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)") run_cmake(HOST_LINK-link_depends) endif() diff --git a/Tests/RunCMake/Ninja/MyWindow.cpp b/Tests/RunCMake/Ninja/MyWindow.cpp new file mode 100644 index 0000000..d87c2e9 --- /dev/null +++ b/Tests/RunCMake/Ninja/MyWindow.cpp @@ -0,0 +1,7 @@ +#include "MyWindow.h" + +MyWindow::MyWindow(QWidget* parent) + : QWidget(parent) +{ + this->m_ui.setupUi(this); +} diff --git a/Tests/RunCMake/Ninja/MyWindow.h b/Tests/RunCMake/Ninja/MyWindow.h new file mode 100644 index 0000000..c267610 --- /dev/null +++ b/Tests/RunCMake/Ninja/MyWindow.h @@ -0,0 +1,16 @@ +#pragma once + +#include <QWidget> + +#include "ui_MyWindow.h" + +class MyWindow : public QWidget +{ + Q_OBJECT + +public: + explicit MyWindow(QWidget* parent = nullptr); + +private: + Ui::MyWindow m_ui; +}; diff --git a/Tests/RunCMake/Ninja/MyWindow.ui b/Tests/RunCMake/Ninja/MyWindow.ui new file mode 100644 index 0000000..fbf294c --- /dev/null +++ b/Tests/RunCMake/Ninja/MyWindow.ui @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MyWindow</class> + <widget class="QWidget" name="MyWindow"/> +</ui> diff --git a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake index 7456608..46b840f 100644 --- a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake +++ b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake @@ -8,6 +8,14 @@ add_library(simple_lib SHARED simple_lib.cpp) add_executable(app_with_qt app.cpp app_qt.cpp) target_link_libraries(app_with_qt PRIVATE simple_lib Qt5::Core) +if(Qt5Widgets_DIR) + find_package(Qt5Widgets REQUIRED) + qt5_wrap_ui(_headers MyWindow.ui) + add_executable(app_with_widget app.cpp MyWindow.cpp ${_headers}) + target_link_libraries(app_with_widget PRIVATE Qt5::Widgets) + target_include_directories(app_with_widget PRIVATE "${CMAKE_BINARY_DIR}") +endif() + add_subdirectory(QtSubDir1) add_subdirectory(QtSubDir2) add_subdirectory(QtSubDir3) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 1b252cd..0c0619d 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -186,16 +186,6 @@ function(sleep delay) endif() endfunction(sleep) -function(touch path) - execute_process( - COMMAND ${CMAKE_COMMAND} -E touch ${path} - RESULT_VARIABLE result - ) - if(NOT result EQUAL 0) - message(FATAL_ERROR "failed to touch main ${path} file.") - endif() -endfunction(touch) - macro(ninja_escape_path path out) string(REPLACE "\$ " "\$\$" "${out}" "${path}") string(REPLACE " " "\$ " "${out}" "${${out}}") @@ -264,8 +254,8 @@ build build.ninja: RERUN ${escaped_build_ninja_dep} || ${escaped_ninja_output_pa # Test regeneration rules run in order. set(main_cmakelists "${RunCMake_SOURCE_DIR}/CMakeLists.txt") sleep(${fs_delay}) - touch("${main_cmakelists}") - touch("${build_ninja_dep}") + file(TOUCH "${main_cmakelists}") + file(TOUCH "${build_ninja_dep}") run_ninja("${top_build_dir}") file(TIMESTAMP "${main_cmakelists}" mtime_main_cmakelists UTC) file(TIMESTAMP "${sub_build_ninja}" mtime_sub_build_ninja UTC) @@ -329,14 +319,14 @@ run_ChangeBuildType() function(run_Qt5AutoMocDeps) if(CMake_TEST_Qt5 AND CMAKE_TEST_Qt5Core_Version VERSION_GREATER_EQUAL 5.15.0) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5AutoMocDeps-build) - set(RunCMake_TEST_OPTIONS "-DQt5Core_DIR=${Qt5Core_DIR}") + set(RunCMake_TEST_OPTIONS "-DQt5Core_DIR=${Qt5Core_DIR}" "-DQt5Widgets_DIR=${Qt5Widgets_DIR}") run_cmake(Qt5AutoMocDeps) unset(RunCMake_TEST_OPTIONS) # Build the project. run_ninja("${RunCMake_TEST_BINARY_DIR}") # Touch just the library source file, which shouldn't cause a rerun of AUTOMOC # for app_with_qt target. - touch("${RunCMake_SOURCE_DIR}/simple_lib.cpp") + file(TOUCH "${RunCMake_SOURCE_DIR}/simple_lib.cpp") # Build and assert that AUTOMOC was not run for app_with_qt. run_ninja("${RunCMake_TEST_BINARY_DIR}") if(ninja_stdout MATCHES "Automatic MOC for target app_with_qt") @@ -352,6 +342,11 @@ function(run_Qt5AutoMocDeps) message(FATAL_ERROR "AUTOMOC should not have executed for 'sub_exe_2' target:\nstdout:\n${ninja_stdout}") endif() + # Touch a header file to make sure an automoc dependency cycle is not introduced. + file(TOUCH "${RunCMake_SOURCE_DIR}/MyWindow.h") + run_ninja("${RunCMake_TEST_BINARY_DIR}") + # Need to run a second time to hit the dependency cycle. + run_ninja("${RunCMake_TEST_BINARY_DIR}") endif() endfunction() run_Qt5AutoMocDeps() diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-in-release-graph-ninja-stdout.txt new file mode 100644 index 0000000..3c92457 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-in-release-graph-ninja-stdout.txt @@ -0,0 +1,4 @@ +^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj) +\[2/3\] Linking C executable Release[\/]echo(\.exe)? +\[3/3\] Generating echo_dbg_Debug\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Debug' 'echo_dbg_Debug\.txt'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-ninja-stdout.txt new file mode 100644 index 0000000..2ab35a7 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-ninja-stdout.txt @@ -0,0 +1,4 @@ +^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj) +\[2/3\] Linking C executable Debug[\/]echo(\.exe)? +\[3/3\] Generating echo_dbg_Debug\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_dbg_Debug\.txt'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-release-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-release-ninja-stdout.txt new file mode 100644 index 0000000..4b1473d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-release-ninja-stdout.txt @@ -0,0 +1,2 @@ +^\[1/2\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj) +\[2/2\] Linking C executable Release[\/]echo(\.exe)?$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-in-release-graph-ninja-stdout.txt new file mode 100644 index 0000000..25c357c --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-in-release-graph-ninja-stdout.txt @@ -0,0 +1,4 @@ +^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj) +\[2/3\] Linking C executable Release[\/]echo(\.exe)? +\[3/3\] Generating echo_dbgx_Debug\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Debug' 'echo_dbgx_Debug\.txt' 'echo_dbgx_byproduct_Debug\.txt'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-ninja-stdout.txt new file mode 100644 index 0000000..153906d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-ninja-stdout.txt @@ -0,0 +1,4 @@ +^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj) +\[2/3\] Linking C executable Debug[\/]echo(\.exe)? +\[3/3\] Generating echo_dbgx_Debug\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_dbgx_Debug\.txt' 'echo_dbgx_byproduct_Debug\.txt'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-release-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-release-ninja-stdout.txt new file mode 100644 index 0000000..32aa070 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-release-ninja-stdout.txt @@ -0,0 +1,5 @@ +^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj) +\[2/3\] Linking C executable Release[\/]echo(\.exe)? +\[3/3\] [^ +]* +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release' 'echo_dbgx_byproduct_Release\.txt'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt index 45f2e57..d90a2f3 100644 --- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt @@ -1,5 +1,4 @@ -^(Recompacting log\.\.\. -)?\[1/2\] Generating depend_Debug\.txt +^\[1/2\] Generating depend_Debug\.txt depend_Debug\.txt \[2/2\] echo_target_depend_out echo_target_depend_out_Debug\.txt$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake index 5d6f421..e49cc32 100644 --- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake @@ -119,6 +119,30 @@ foreach(case add_custom_target(${case} DEPENDS ${case}_$<CONFIG>.txt) endforeach() +# An OUTPUT in only one configuration. +add_custom_command( + OUTPUT "$<$<CONFIG:Debug>:echo_dbg_Debug.txt>" + COMMAND echo $<CONFIG> "$<$<CONFIG:Debug>:echo_dbg_Debug.txt>" + ) +set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/echo_dbg_Debug.txt PROPERTY SYMBOLIC 1) +add_custom_target(echo_dbg DEPENDS "$<$<CONFIG:Debug>:echo_dbg_Debug.txt>") + +# An OUTPUT in only one configuration with BYPRODUCTS in every configuration. +add_custom_command( + OUTPUT "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>" + BYPRODUCTS echo_dbgx_byproduct_$<CONFIG>.txt + COMMAND echo $<CONFIG> "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>" echo_dbgx_byproduct_$<CONFIG>.txt + COMMAND_EXPAND_LISTS + ) + set_property(SOURCE + ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_Debug.txt + ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_Debug.txt + ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_Release.txt + ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_MinSizeRel.txt + ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_RelWithDebInfo.txt + PROPERTY SYMBOLIC 1) +add_custom_target(echo_dbgx DEPENDS "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>") + add_custom_target(echo_target_raw BYPRODUCTS echo_target_raw_$<CONFIG>.txt COMMENT echo_target_raw diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 0d4db52..23b4aea 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -323,6 +323,20 @@ run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct_if-debug build-Debug. run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean) run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct_if-debug-in-release-graph build-Release.ninja echo_no_cross_byproduct_if:Debug) run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) +# echo_dbg +run_ninja(CustomCommandOutputGenex echo_dbg-debug build-Debug.ninja echo_dbg) +run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean) +run_ninja(CustomCommandOutputGenex echo_dbg-release build-Release.ninja echo_dbg) +run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) +run_ninja(CustomCommandOutputGenex echo_dbg-debug-in-release-graph build-Release.ninja echo_dbg:Debug) +run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) +# echo_dbgx +run_ninja(CustomCommandOutputGenex echo_dbgx-debug build-Debug.ninja echo_dbgx) +run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean) +run_ninja(CustomCommandOutputGenex echo_dbgx-release build-Release.ninja echo_dbgx) +run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) +run_ninja(CustomCommandOutputGenex echo_dbgx-debug-in-release-graph build-Release.ninja echo_dbgx:Debug) +run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) # echo_target_raw run_ninja(CustomCommandOutputGenex echo_target_raw-debug build-Debug.ninja echo_target_raw:Debug) run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 3ea4ae5..7994fc2 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -144,6 +144,7 @@ function(run_cmake test) "|clang[^:]*: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled:" "|Error kstat returned" "|Hit xcodebuild bug" + "|Recompacting log\\.\\.\\." "|LICENSE WARNING:" "|Your license to use PGI[^\n]*expired" diff --git a/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake b/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake new file mode 100644 index 0000000..a26c278 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake @@ -0,0 +1,10 @@ + +cmake_policy(VERSION 3.1) + +file(STRINGS "${RunCMake_TEST_BINARY_DIR}/CMP0122-library-name.txt" prefixes) + +list(GET prefixes 0 std_prefix) +list(GET prefixes 1 lib_prefix) +if (NOT std_prefix STREQUAL lib_prefix) + string (APPEND RunCMake_TEST_FAILED "\nFound prefix: '${lib_prefix}', expected: '${std_prefix}'.") +endif() diff --git a/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake b/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake new file mode 100644 index 0000000..fecb7db --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0122 NEW) +include(CMP0122-common.cmake) diff --git a/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake b/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake new file mode 100644 index 0000000..01657d0 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake @@ -0,0 +1,10 @@ + +cmake_policy(VERSION 3.1) + +file(STRINGS "${RunCMake_TEST_BINARY_DIR}/CMP0122-library-name.txt" prefixes) + +list(GET prefixes 1 lib_prefix) +if (lib_prefix) + # prefix must be empty + string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix: '${lib_prefix}'.") +endif() diff --git a/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake b/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake new file mode 100644 index 0000000..a787b68 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0122 OLD) +include(CMP0122-common.cmake) diff --git a/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt new file mode 100644 index 0000000..37c4fbd --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt @@ -0,0 +1,10 @@ +CMake Warning \(dev\) at .*/Modules/UseSWIG.cmake:[0-9]+ \(message\): + Policy CMP0122 is not set: UseSWIG use standard library name conventions + for csharp language\. Run "cmake --help-policy CMP0122" for policy details\. + Use the cmake_policy command to set the policy and suppress this warning\. + +Call Stack \(most recent call first\): + CMP0122-common.cmake:9 \(swig_add_library\) + CMP0122-WARN.cmake:1 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake b/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake new file mode 100644 index 0000000..5d571aa --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake @@ -0,0 +1 @@ +include(CMP0122-common.cmake) diff --git a/Tests/RunCMake/UseSWIG/CMP0122-common.cmake b/Tests/RunCMake/UseSWIG/CMP0122-common.cmake new file mode 100644 index 0000000..be880ec --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-common.cmake @@ -0,0 +1,12 @@ + +cmake_policy(SET CMP0078 NEW) +cmake_policy(SET CMP0086 NEW) + +set(SWIG_EXECUTABLE "swig") +set(SWIG_DIR "/swig") +include(UseSWIG) + +swig_add_library(example LANGUAGE csharp TYPE SHARED SOURCES example.i) + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/CMP0122-library-name.txt" + CONTENT "${CMAKE_SHARED_LIBRARY_PREFIX}\n$<TARGET_FILE_PREFIX:example>\n") diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake index 6acf719..c7a118f 100644 --- a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake +++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake @@ -23,3 +23,7 @@ if (CMake_TEST_FindPython) run_cmake_target(CMP0086-NEW build example) endif() + +run_cmake(CMP0122-WARN) +run_cmake(CMP0122-OLD) +run_cmake(CMP0122-NEW) diff --git a/Tests/RunCMake/configure_file/SourcePermissions-result.txt b/Tests/RunCMake/configure_file/SourcePermissions-result.txt deleted file mode 100644 index e69de29..0000000 --- a/Tests/RunCMake/configure_file/SourcePermissions-result.txt +++ /dev/null diff --git a/Tests/RunCMake/configure_file/SourcePermissions-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissions-stderr.txt deleted file mode 100644 index e69de29..0000000 --- a/Tests/RunCMake/configure_file/SourcePermissions-stderr.txt +++ /dev/null diff --git a/Tests/RunCMake/configure_file/SourcePermissions.cmake b/Tests/RunCMake/configure_file/SourcePermissions.cmake index 50330fc..c4d3d61 100644 --- a/Tests/RunCMake/configure_file/SourcePermissions.cmake +++ b/Tests/RunCMake/configure_file/SourcePermissions.cmake @@ -6,17 +6,17 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt WORLD_READ ) -if (UNIX) +if (CMAKE_HOST_UNIX) find_program(STAT_EXECUTABLE NAMES stat) if(NOT STAT_EXECUTABLE) return() endif() - if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + if (CMAKE_HOST_SYSTEM_NAME MATCHES "FreeBSD") execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt" OUTPUT_VARIABLE output ) - elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") + elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt" OUTPUT_VARIABLE output ) diff --git a/Tests/RunCMake/configure_file/UseSourcePermissions.cmake b/Tests/RunCMake/configure_file/UseSourcePermissions.cmake index f7aedd1..65e5954 100644 --- a/Tests/RunCMake/configure_file/UseSourcePermissions.cmake +++ b/Tests/RunCMake/configure_file/UseSourcePermissions.cmake @@ -3,20 +3,20 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt USE_SOURCE_PERMISSIONS ) -if (UNIX) +if (CMAKE_HOST_UNIX) find_program(STAT_EXECUTABLE NAMES stat) if(NOT STAT_EXECUTABLE) return() endif() - if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + if (CMAKE_HOST_SYSTEM_NAME MATCHES "FreeBSD") execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt" OUTPUT_VARIABLE output1 ) execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt" OUTPUT_VARIABLE output2 ) - elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") + elseif (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt" OUTPUT_VARIABLE output1 ) diff --git a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake index 8ef13f9..a707383 100644 --- a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake @@ -17,6 +17,9 @@ if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel") if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release) endif() + if (RunCMake_GENERATOR MATCHES "Ninja") + set(VERBOSE -- -v) + endif() run_cmake(LINK_OPTIONS) @@ -56,6 +59,10 @@ if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel") run_cmake_target(genex_DEVICE_LINK CMP0105_OLD LinkOptions_CMP0105_OLD --config Release) run_cmake_target(genex_DEVICE_LINK CMP0105_NEW LinkOptions_CMP0105_NEW --config Release) run_cmake_target(genex_DEVICE_LINK device LinkOptions_device --config Release) + + if (RunCMake_GENERATOR MATCHES "(Ninja|Unix Makefiles)") + run_cmake_target(genex_DEVICE_LINK host_link_options LinkOptions_host_link_options --config Release ${VERBOSE}) + endif() endif() run_cmake_target(genex_DEVICE_LINK no_device LinkOptions_no_device --config Release) diff --git a/Tests/RunCMake/target_link_options/genex_DEVICE_LINK-host_link_options-check.cmake b/Tests/RunCMake/target_link_options/genex_DEVICE_LINK-host_link_options-check.cmake new file mode 100644 index 0000000..31ffe7f --- /dev/null +++ b/Tests/RunCMake/target_link_options/genex_DEVICE_LINK-host_link_options-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "-Xlinker=OPT1 -Xlinker=OPT2 -Xlinker=OPT3 -Xlinker=OPT4 -Xlinker=OPT5") + set (RunCMake_TEST_FAILED "Not found expected '-Xlinker=OPT1 -Xlinker=OPT2 -Xlinker=OPT3 -Xlinker=OPT4 -Xlinker=OPT5'.") +endif() diff --git a/Tests/RunCMake/target_link_options/genex_DEVICE_LINK-host_link_options-result.txt b/Tests/RunCMake/target_link_options/genex_DEVICE_LINK-host_link_options-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_options/genex_DEVICE_LINK-host_link_options-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_options/genex_DEVICE_LINK.cmake b/Tests/RunCMake/target_link_options/genex_DEVICE_LINK.cmake index 0126080..a53ab20 100644 --- a/Tests/RunCMake/target_link_options/genex_DEVICE_LINK.cmake +++ b/Tests/RunCMake/target_link_options/genex_DEVICE_LINK.cmake @@ -1,6 +1,10 @@ enable_language(C) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE) + set (obj "${CMAKE_C_OUTPUT_EXTENSION}") if(BORLAND) set(pre -) @@ -43,6 +47,10 @@ if (CMake_TEST_CUDA) set_property(TARGET LinkOptions_device PROPERTY CUDA_SEPARABLE_COMPILATION ON) target_link_options(LinkOptions_device PRIVATE $<DEVICE_LINK:${pre}BADFLAG_DEVICE_LINK${obj}> $<HOST_LINK:${pre}BADFLAG_NORMAL_LINK${obj}>) + + add_executable(LinkOptions_host_link_options LinkOptionsDevice.cu) + set_property(TARGET LinkOptions_host_link_options PROPERTY CUDA_SEPARABLE_COMPILATION ON) + target_link_options(LinkOptions_host_link_options PRIVATE -Wl,OPT1 -Xlinker=OPT2 "SHELL:-Xlinker OPT3" "SHELL:LINKER:OPT4 LINKER:OPT5") endif() add_executable(LinkOptions_no_device LinkOptionsDevice.cu) |