Merge topic 'if-invalid' 240481490c if: Diagnose invalid argument in parentheses Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !12114
diff --git a/.gitlab/ci/configure_fedora44_makefiles.cmake b/.gitlab/ci/configure_fedora44_makefiles.cmake index 2cd93f4..49ed52f 100644 --- a/.gitlab/ci/configure_fedora44_makefiles.cmake +++ b/.gitlab/ci/configure_fedora44_makefiles.cmake
@@ -112,6 +112,7 @@ set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "") set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "") set(CMake_TEST_Qt5 "ON" CACHE BOOL "") +set(CMake_TEST_Rust "ON" CACHE STRING "") set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "") set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "") set(CMake_TEST_TLS_VERSION "1.3" CACHE STRING "")
diff --git a/CMakeLists.txt b/CMakeLists.txt index 866390c..4f8a022 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -611,6 +611,7 @@ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE REGEX "Help/(dev|guide)($|/)" EXCLUDE + PATTERN ".git*" EXCLUDE ) # Install auxiliary files integrating with other tools.
diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst index bbfcca2..919b107 100644 --- a/Help/command/add_test.rst +++ b/Help/command/add_test.rst
@@ -8,7 +8,8 @@ add_test(NAME <name> COMMAND <command> [<arg>...] [CONFIGURATIONS <config>...] [WORKING_DIRECTORY <dir>] - [COMMAND_EXPAND_LISTS]) + [COMMAND_EXPAND_LISTS] + [BUILD_DEPENDS <dependencies>...]) Adds a test called ``<name>``. The test name may contain arbitrary characters, expressed as a :ref:`Quoted Argument` or :ref:`Bracket Argument` @@ -59,6 +60,25 @@ <launcher> <emulator> <command> + * .. versionadded:: 4.4 + + When the :variable:`CMAKE_TEST_BUILD_DEPENDS` variable is enabled, + the :ref:`Ninja Generators` generate a convenience build target named + ``test_prep/<name>`` that depends on the test executable target. Building + this target ensures the executable is up-to-date before the test runs. + + Additionally, targets referenced by the test command via generator + expressions are added as dependencies of the ``test_prep/<name>`` target. + + If multiple tests in different directories share the same name, their + dependencies are merged into a single ``test_prep/<name>`` target. + + Tests with names that are not valid target names are excluded from this + behavior. + + The ``BUILD_DEPENDS`` keyword can be used to add explicit build + dependencies. + The command may be specified using :manual:`generator expressions <cmake-generator-expressions(7)>`. @@ -71,6 +91,15 @@ :variable:`CMAKE_CURRENT_BINARY_DIR`. The working directory may be specified using :manual:`generator expressions <cmake-generator-expressions(7)>`. +``BUILD_DEPENDS`` + .. versionadded:: 4.4 + + Specify a list of targets or files that must be built before the test can + run. Each dependency is added to the ``test_prep/<name>`` build target + described above when :variable:`CMAKE_TEST_BUILD_DEPENDS` is enabled + with the :ref:`Ninja Generators`. The test name must be a valid target name + in order to list build dependencies with this keyword. + ``COMMAND_EXPAND_LISTS`` .. versionadded:: 3.16
diff --git a/Help/command/ctest_build.rst b/Help/command/ctest_build.rst index 8a83107..07ceadc 100644 --- a/Help/command/ctest_build.rst +++ b/Help/command/ctest_build.rst
@@ -86,13 +86,20 @@ argument will override the :preset:`buildPresets.targets` setting from the chosen preset. + See also the :variable:`CTEST_BUILD_PRESET` and + :variable:`CTEST_PRESET` variables. + ``PRESETS_FILE <file>`` .. versionadded:: 4.4 Specify a :manual:`presets <cmake-presets(7)>` file to use instead of the default ``CMakePresets.json`` in the source directory. A relative path is interpreted relative to the source directory. - Has no effect unless ``PRESET`` is also specified. + Has no effect unless a preset is selected via the ``PRESET`` argument + or the :variable:`CTEST_BUILD_PRESET` or :variable:`CTEST_PRESET` + variables. + + See also the :variable:`CTEST_PRESETS_FILE` variable. ``RETURN_VALUE <result-var>`` Store the return value of the native build tool in the given variable.
diff --git a/Help/command/ctest_configure.rst b/Help/command/ctest_configure.rst index 7a273cd..4317875 100644 --- a/Help/command/ctest_configure.rst +++ b/Help/command/ctest_configure.rst
@@ -49,13 +49,20 @@ This option is ignored when :variable:`CTEST_CONFIGURE_COMMAND` is used. + See also the :variable:`CTEST_CONFIGURE_PRESET` and + :variable:`CTEST_PRESET` variables. + ``PRESETS_FILE <file>`` .. versionadded:: 4.4 Specify a :manual:`presets <cmake-presets(7)>` file to use instead of the default ``CMakePresets.json`` in the source directory. A relative path is interpreted relative to the source directory. - Has no effect unless ``PRESET`` is also specified. + Has no effect unless a preset is selected via the ``PRESET`` argument + or the :variable:`CTEST_CONFIGURE_PRESET` or :variable:`CTEST_PRESET` + variables. + + See also the :variable:`CTEST_PRESETS_FILE` variable. ``RETURN_VALUE <result-var>`` Store in the ``<result-var>`` variable the return value of the native
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index ed44aa4..e5a174c 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst
@@ -201,13 +201,22 @@ the :preset:`filter.include.name <testPresets.filter.include.name>` setting from the chosen preset. + This option also applies to the :command:`ctest_memcheck` command. + See also the :variable:`CTEST_TEST_PRESET` and + :variable:`CTEST_PRESET` variables. + ``PRESETS_FILE <file>`` .. versionadded:: 4.4 Specify a :manual:`presets <cmake-presets(7)>` file to use instead of the default ``CMakePresets.json`` in the source directory. A relative path is interpreted relative to the source directory. - Has no effect unless ``PRESET`` is also specified. + Has no effect unless a preset is selected via the ``PRESET`` argument + or the :variable:`CTEST_TEST_PRESET` or :variable:`CTEST_PRESET` + variables. + + This option also applies to the :command:`ctest_memcheck` command. + See also the :variable:`CTEST_PRESETS_FILE` variable. ``QUIET`` .. versionadded:: 3.3
diff --git a/Help/command/if.rst b/Help/command/if.rst index 6433e45..3ef7b54 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst
@@ -93,6 +93,11 @@ to ``NEW`` and the string's value happens to be a variable name that is affected by :policy:`CMP0054`'s behavior. +.. signature:: if() + :target: empty + + False if no argument is provided. + Logic Operators """""""""""""""
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index fb93e24..9fd95e8 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst
@@ -127,7 +127,7 @@ In order to activate support for Rust, set * variable ``CMAKE_EXPERIMENTAL_RUST`` to -* value ``efaed83b-d73a-48af-999a-bd0a6172c313``. +* value ``b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1``. This UUID may change in future versions of CMake. Be sure to use the value documented here by the source tree of the version of CMake with which you are
diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst index 5f5ffb8..d90e8c5 100644 --- a/Help/generator/Ninja.rst +++ b/Help/generator/Ninja.rst
@@ -31,6 +31,26 @@ Created only if the :prop_gbl:`INSTALL_PARALLEL` global property is ``ON``. Runs the install step for each subdirectory independently and in parallel. +``test_prep/<test-name>`` + + .. versionadded:: 4.4 + + Created only if the :variable:`CMAKE_TEST_BUILD_DEPENDS` variable is + enabled. Builds all known build dependencies for the named test, including + the executable target invoked by the test, targets referenced by generator + expressions in the test command, and explicit ``BUILD_DEPENDS`` entries. + + Tests with names that are not valid target names are excluded. If multiple + tests in different directories share the same name, their dependencies are + merged into one ``test_prep/<test-name>`` target. + +``test_prep/all`` + + .. versionadded:: 4.4 + + Created only if the :variable:`CMAKE_TEST_BUILD_DEPENDS` variable is + enabled. Depends on every generated ``test_prep/<test-name>`` target. + For each subdirectory ``sub/dir`` of the project, additional targets are generated:
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 80692cf..64dd5bd 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst
@@ -636,14 +636,14 @@ ``targets`` array. ``abstractTargetIndexes`` + .. codemodel-versionadded:: 2.9 + Optional member that is present when the directory itself has abstract targets, excluding those belonging to subdirectories. The value is a JSON array of entries corresponding to the abstract targets. Each entry is an unsigned integer 0-based index into the main ``abstractTargets`` array. - This field was added in codemodel version 2.9. - ``minimumCMakeVersion`` Optional member present when a minimum required version of CMake is known for the directory. This is the ``<min>`` version given to the @@ -666,12 +666,12 @@ or equivalent rule is available. ``jsonFile`` + .. codemodel-versionadded:: 2.3 + A JSON string specifying a path relative to the codemodel file to another JSON file containing a `"codemodel" version 2 "directory" object`_. - This field was added in codemodel version 2.3. - ``projects`` A JSON array of entries corresponding to the top-level project and sub-projects defined in the build system. Each (sub-)project @@ -711,14 +711,14 @@ ``targets`` array. ``abstractTargetIndexes`` + .. codemodel-versionadded:: 2.9 + Optional member that is present when the project itself has abstract targets, excluding those belonging to sub-projects. The value is a JSON array of entries corresponding to the abstract targets. Each entry is an unsigned integer 0-based index into the main ``abstractTargets`` array. - This field was added in codemodel version 2.9. - ``targets`` A JSON array of entries corresponding to the build system targets. Such targets are created by calls to :command:`add_executable`, @@ -747,6 +747,8 @@ `"codemodel" version 2 "target" object`_. ``abstractTargets`` + .. codemodel-versionadded:: 2.9 + A JSON array of entries corresponding to targets that are not present in the build system. These are imported targets or interface libraries created by calls to :command:`add_executable` or :command:`add_library`. @@ -777,8 +779,6 @@ to another JSON file containing a `"codemodel" version 2 "target" object`_. - This field was added in codemodel version 2.9. - "codemodel" version 2 "directory" object ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -791,6 +791,8 @@ with members: ``codemodelVersion`` + .. codemodel-versionadded:: 2.9 + This specifies the codemodel version this file is part of. It will match the ``version`` field of the codemodel object kind that references this file. It is a JSON object with the following members: @@ -801,8 +803,6 @@ ``minor`` The codemodel minor version. - This field was added in codemodel version 2.9. - ``paths`` A JSON object containing members: @@ -913,21 +913,21 @@ ``runtimeDependencySetName`` and ``runtimeDependencySetType``. ``fileSet`` + .. codemodel-versionadded:: 2.4 + An :command:`install(TARGETS)` call with ``FILE_SET``. The ``destination`` and ``paths`` members are populated. The ``isOptional`` member may exist. This type has additional members ``fileSetName``, ``fileSetType``, ``fileSetDirectories``, and ``fileSetTarget``. - This type was added in codemodel version 2.4. - ``cxxModuleBmi`` + .. codemodel-versionadded:: 2.5 + An :command:`install(TARGETS)` call with ``CXX_MODULES_BMI``. The ``destination`` member is populated and the ``isOptional`` member may exist. This type has an additional ``cxxModuleBmiTarget`` member. - This type was added in codemodel version 2.5. - ``isExcludeFromAll`` Optional member that is present with boolean value ``true`` when :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option. @@ -1006,29 +1006,32 @@ frameworks. ``fileSetName`` + .. codemodel-versionadded:: 2.4 + Optional member that is present when ``type`` is ``fileSet``. The value is a string with the name of the file set. - This field was added in codemodel version 2.4. - ``fileSetType`` + .. codemodel-versionadded:: 2.4 + Optional member that is present when ``type`` is ``fileSet``. The value is a string with the type of the file set. - This field was added in codemodel version 2.4. + .. codemodel-versionchanged:: 2.11 - Since codemodel version 2.11, this field additionally accounts for - ``SOURCES`` file sets. + This field additionally accounts for ``SOURCES`` file sets. ``fileSetDirectories`` + .. codemodel-versionadded:: 2.4 + Optional member that is present when ``type`` is ``fileSet``. The value is a list of strings with the file set's base directories (determined by genex-evaluation of :prop_tgt:`HEADER_DIRS` or :prop_tgt:`HEADER_DIRS_<NAME>`). - This field was added in codemodel version 2.4. - ``fileSetTarget`` + .. codemodel-versionadded:: 2.4 + Optional member that is present when ``type`` is ``fileSet``. The value is a JSON object with members: @@ -1041,9 +1044,9 @@ An unsigned integer 0-based index into the main "codemodel" object's ``targets`` array for the target. - This field was added in codemodel version 2.4. - ``cxxModuleBmiTarget`` + .. codemodel-versionadded:: 2.5 + Optional member that is present when ``type`` is ``cxxModuleBmi``. The value is a JSON object with members: @@ -1056,8 +1059,6 @@ An unsigned integer 0-based index into the main "codemodel" object's ``targets`` array for the target. - This field was added in codemodel version 2.5. - ``scriptFile`` Optional member that is present when ``type`` is ``script``. The value is a string specifying the path to the script file on disk, @@ -1087,6 +1088,8 @@ with members: ``codemodelVersion`` + .. codemodel-versionadded:: 2.9 + This specifies the codemodel version this file is part of. It will match the ``version`` field of the codemodel object kind that references this file. It is a JSON object with the following members: @@ -1097,8 +1100,6 @@ ``minor`` The codemodel minor version. - This field was added in codemodel version 2.9. - ``name`` A string specifying the logical name of the target. @@ -1113,19 +1114,21 @@ or ``UTILITY``. ``imported`` + .. codemodel-versionadded:: 2.9 + Optional member that is present with boolean value ``true`` if the target is an imported target. - This field was added in codemodel version 2.9. - ``local`` + .. codemodel-versionadded:: 2.9 + Optional member that is present with boolean value ``true`` if the target is only defined with local scope rather than being a global target. Currently, only imported targets will potentially have this field. - This field was added in codemodel version 2.9. - ``abstract`` + .. codemodel-versionadded:: 2.9 + Optional member that is present with boolean value ``true`` if the target is an abstract target. Abstract targets are not part of the build system, they only exist to describe dependencies or to provide usage @@ -1134,17 +1137,17 @@ cannot be built, so they should not be presented to the user as a buildable target. - This field was added in codemodel version 2.9. Abstract targets were not - included in codemodel version 2.8 and earlier. + Abstract targets were not included in codemodel version 2.8 and earlier. ``symbolic`` + .. codemodel-versionadded:: 2.9 + Optional member that is present with boolean value ``true`` if the target is :prop_tgt:`SYMBOLIC`. Symbolic targets are created by calls to :command:`add_library(INTERFACE SYMBOLIC) <add_library(INTERFACE-SYMBOLIC)>`, and are also abstract targets that are not part of the build system. - This field was added in codemodel version 2.9. Symbolic targets were not - included in codemodel version 2.8 and earlier. + Symbolic targets were not included in codemodel version 2.8 and earlier. ``backtrace`` Optional member that is present when a CMake language backtrace to @@ -1223,6 +1226,8 @@ index into the ``backtraceGraph`` member's ``nodes`` array. ``launchers`` + .. codemodel-versionadded:: 2.7 + Optional member that is present on executable targets that have at least one launcher specified by the project. The value is a JSON array of entries corresponding to the specified launchers. @@ -1250,8 +1255,6 @@ A start program for the execution of tests. See the :prop_tgt:`TEST_LAUNCHER` target property. - This field was added in codemodel version 2.7. - ``link`` Optional member that is present for non-imported executables and shared library targets that link into a runtime binary. The value is a JSON object @@ -1323,21 +1326,19 @@ or link-time code generation) is enabled. ``debugger`` + .. codemodel-versionadded:: 2.8 + Optional member that is present when the target has one of the following fields set. The value is a JSON object of entries corresponding to debugger specific values set. - This field was added in codemodel version 2.8. - ``workingDirectory`` Optional member that is present when the :prop_tgt:`DEBUGGER_WORKING_DIRECTORY` target property is set. The member will also be present in :ref:`Visual Studio Generators` when :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` is set. - This field was added in codemodel version 2.8. - ``dependencies`` Optional member that is present when the target depends on other targets. It is only present if the target is part of the build system. @@ -1367,6 +1368,8 @@ the ``backtraceGraph`` member's ``nodes`` array. ``linkLibraries`` + .. codemodel-versionadded:: 2.9 + Optional member that may be present when the target links directly to one or more other targets or libraries. It contains items that are used when linking this target. These come from the target's @@ -1416,9 +1419,9 @@ :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` property created the relationship. The value matches the main ``id`` member of that target. - This field was added in codemodel version 2.9. - ``interfaceLinkLibraries`` + .. codemodel-versionadded:: 2.9 + Optional member that may be present when the target has one or more interface link libraries. It contains items that are used when linking consumers of this target. These come from the target's @@ -1456,9 +1459,9 @@ The value is an unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.9. - ``compileDependencies`` + .. codemodel-versionadded:: 2.9 + Optional member that may be present when the target links directly to one or more other targets that may provide usage requirements to this one. They affect how this target's sources are compiled. These relationships are @@ -1498,9 +1501,9 @@ :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` property created the relationship. The value matches the main ``id`` member of that target. - This field was added in codemodel version 2.9. - ``interfaceCompileDependencies`` + .. codemodel-versionadded:: 2.9 + Optional member that may be present when the target has one or more interface linking relationships to other targets. It contains items that affect how consumers' sources are compiled. These relationships are defined by the @@ -1528,9 +1531,9 @@ The value is an unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.9. - ``objectDependencies`` + .. codemodel-versionadded:: 2.9 + Optional member that is present when the target has one or more entries in its :prop_tgt:`SOURCES` property where the entry is specified using :genex:`$<TARGET_OBJECTS:...>`, and where no other generator expression is @@ -1550,9 +1553,9 @@ The value is an unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.9. - ``orderDependencies`` + .. codemodel-versionadded:: 2.9 + Optional member that is present when the target has one or more direct order dependencies on other targets. Such dependencies may arise from calls to :command:`add_dependencies` or from internal CMake processing. @@ -1574,9 +1577,9 @@ The value is an unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.9. - ``fileSets`` + .. codemodel-versionadded:: 2.5 + An optional member that is present when a target defines one or more file sets. The value is a JSON array of entries corresponding to the target's file sets. Each entry is a JSON object with members: @@ -1598,8 +1601,6 @@ directory then the path is specified relative to that directory. Otherwise the path is absolute. - This field was added in codemodel version 2.5. - ``sources`` A JSON array of entries corresponding to the target's source files. Each entry is a JSON object with members: @@ -1626,6 +1627,8 @@ the source is :prop_sf:`GENERATED`. ``fileSetIndex`` + .. codemodel-versionadded:: 2.5 + .. deprecated:: 4.4 Use the ``fileSetIndexes`` field instead, which is an array, and accounts for sources assigned to multiple file sets. @@ -1634,15 +1637,13 @@ The value is an unsigned integer 0-based index into the ``fileSets`` array representing the file set to which the source was most recently added. - This field was added in codemodel version 2.5. - ``fileSetIndexes`` + .. codemodel-versionadded:: 2.11 + Optional member that is present when the source is part of at least one file set; see also policy :policy:`CMP0211`. The value is an array of unsigned integer 0-based indexes inte the ``fileSets`` array. - This field was added in codemodel version 2.11. - ``backtrace`` .. deprecated:: 4.4 Use the ``backtraces`` field instead, which is an array, and @@ -1657,6 +1658,7 @@ the ``backtraceGraph`` member's ``nodes`` array. ``backtraces`` + .. codemodel-versionadded:: 2.11 Optional member that is present when CMake language backtraces to the :command:`target_sources`, :command:`add_executable`, @@ -1669,9 +1671,9 @@ unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.11. - ``interfaceSources`` + .. codemodel-versionadded:: 2.10 + An optional member that is present when a target defines one or more interface sources. The value is a JSON array of entries corresponding to the target's interface source files. Each entry is a JSON object @@ -1703,14 +1705,12 @@ array representing the file set to which the source was most recently added. ``fileSetIndexes`` + .. codemodel-versionadded:: 2.11 + Optional member that is present when the source is part of at least one file set; see also policy :policy:`CMP0211`. The value is an array of unsigned integer 0-based indexes inte the ``fileSets`` array. - This field was added in codemodel version 2.11. - - This field was added in codemodel version 2.10. - ``sourceGroups`` Optional member that is present when sources are grouped together by the :command:`source_group` command or by default. The value is a @@ -1726,14 +1726,14 @@ main ``sources`` array for the target. ``interfaceSourceIndexes`` + .. codemodel-versionadded:: 2.10 + Optional member that is present when at least one interface source file is part of the source group. The value is a JSON array listing the interface sources belonging to the group. Each entry is an unsigned integer 0-based index into the main ``interfaceSources`` array for the target. - This field was added in codemodel version 2.10. - ``compileGroups`` Optional member that is present when the target has sources that compile. The value is a JSON array of entries corresponding to groups of sources @@ -1750,6 +1750,8 @@ of the toolchain is used to compile the source file. ``languageStandard`` + .. codemodel-versionadded:: 2.2 + Optional member that is present when the language standard is set explicitly (e.g. via :prop_tgt:`CXX_STANDARD`) or implicitly by compile features. Each entry is a JSON object with two members: @@ -1767,8 +1769,6 @@ ``standard`` String representing the language standard. - This field was added in codemodel version 2.2. - ``compileCommandFragments`` Optional member that is present when fragments of the compiler command line invocation are available. The value is a JSON array of entries @@ -1806,6 +1806,8 @@ member's ``nodes`` array. ``frameworks`` + .. codemodel-versionadded:: 2.6 + Optional member that is present when, on Apple platforms, there are frameworks. The value is a JSON array with an entry for each directory. Each entry is a JSON object with members: @@ -1825,9 +1827,9 @@ an unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.6. - ``precompileHeaders`` + .. codemodel-versionadded:: 2.1 + Optional member that is present when :command:`target_precompile_headers` or other command invocations set :prop_tgt:`PRECOMPILE_HEADERS` on the target. The value is a JSON array with an entry for each header. Each @@ -1843,8 +1845,6 @@ unsigned integer 0-based index into the ``backtraceGraph`` member's ``nodes`` array. - This field was added in codemodel version 2.1. - ``defines`` Optional member that is present when there are preprocessor definitions. The value is a JSON array with an entry for each definition. Each @@ -2134,6 +2134,8 @@ if the path specifies a file in the CMake installation. ``globsDependent`` + .. cmakefiles-versionadded:: 1.1 + Optional member that is present when the project calls :command:`file(GLOB)` or :command:`file(GLOB_RECURSE)` with the ``CONFIGURE_DEPENDS`` option. The value is a JSON array of JSON objects, each specifying a globbing @@ -2141,8 +2143,6 @@ no longer matches the same list of paths, CMake considers the build system to be out of date. - This field was added in ``cmakeFiles`` version 1.1. - The members of each entry are: ``expression`` @@ -2278,6 +2278,8 @@ language. Its value is a JSON string holding the path to the compiler. ``commandFragment`` + .. toolchains-versionadded:: 1.1 + Optional member that is present when the :variable:`CMAKE_<LANG>_COMPILER` variable is a list containing multiple elements or the :envvar:`CC` or similar environment variable contains @@ -2285,8 +2287,6 @@ Its value is a JSON string holding the second and further elements (mandatory arguments to the compiler) as a command line fragment. - This field was added in toolchains version 1.1. - ``id`` Optional member that is present when the :variable:`CMAKE_<LANG>_COMPILER_ID` variable is defined for the current
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 9b9208f..360d369 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst
@@ -143,6 +143,7 @@ /variable/CMAKE_Swift_MODULE_DIRECTORY /variable/CMAKE_Swift_NUM_THREADS /variable/CMAKE_Swift_SEPARATE_MODULE_EMISSION + /variable/CMAKE_TEST_BUILD_DEPENDS /variable/CMAKE_TEST_LAUNCHER /variable/CMAKE_TOOLCHAIN_FILE /variable/CMAKE_TWEAK_VERSION @@ -738,12 +739,14 @@ /variable/CTEST_BINARY_DIRECTORY /variable/CTEST_BUILD_COMMAND /variable/CTEST_BUILD_NAME + /variable/CTEST_BUILD_PRESET /variable/CTEST_BZR_COMMAND /variable/CTEST_BZR_UPDATE_OPTIONS /variable/CTEST_CHANGE_ID /variable/CTEST_CHECKOUT_COMMAND /variable/CTEST_CONFIGURATION_TYPE /variable/CTEST_CONFIGURE_COMMAND + /variable/CTEST_CONFIGURE_PRESET /variable/CTEST_COVERAGE_COMMAND /variable/CTEST_COVERAGE_EXTRA_FLAGS /variable/CTEST_CUSTOM_COVERAGE_EXCLUDE @@ -792,6 +795,8 @@ /variable/CTEST_P4_COMMAND /variable/CTEST_P4_OPTIONS /variable/CTEST_P4_UPDATE_OPTIONS + /variable/CTEST_PRESET + /variable/CTEST_PRESETS_FILE /variable/CTEST_RESOURCE_SPEC_FILE /variable/CTEST_RUN_CURRENT_SCRIPT /variable/CTEST_SCRIPT_DIRECTORY @@ -803,6 +808,7 @@ /variable/CTEST_SVN_OPTIONS /variable/CTEST_SVN_UPDATE_OPTIONS /variable/CTEST_TEST_LOAD + /variable/CTEST_TEST_PRESET /variable/CTEST_TEST_TIMEOUT /variable/CTEST_TEST_COVERAGE_TOOL /variable/CTEST_TLS_VERIFY
diff --git a/Help/release/dev/ctest-script-preset-arg.rst b/Help/release/dev/ctest-script-preset-arg.rst index 7732677..5d0530f 100644 --- a/Help/release/dev/ctest-script-preset-arg.rst +++ b/Help/release/dev/ctest-script-preset-arg.rst
@@ -1,7 +1,14 @@ ctest-script-preset-arg ------------------------ -* The :command:`ctest_configure`, :command:`ctest_build`, +* The :command:`ctest_configure`, :command:`ctest_build`, :command:`ctest_test`, and :command:`ctest_memcheck` commands gained ``PRESET`` and ``PRESETS_FILE`` arguments to support using :manual:`presets <cmake-presets(7)>` for their :ref:`Dashboard Client` steps. + +* The :variable:`CTEST_CONFIGURE_PRESET`, :variable:`CTEST_BUILD_PRESET`, + :variable:`CTEST_TEST_PRESET`, :variable:`CTEST_PRESET`, and + :variable:`CTEST_PRESETS_FILE` variables may be used to specify preset + arguments to the above commands in a :ref:`Dashboard Client` script or + on the :program:`ctest` command line via the + :ref:`-D <ctest-option-D-var>` option.
diff --git a/Help/release/dev/test-dependency-targets.rst b/Help/release/dev/test-dependency-targets.rst new file mode 100644 index 0000000..54d6b5a --- /dev/null +++ b/Help/release/dev/test-dependency-targets.rst
@@ -0,0 +1,15 @@ +test-build-dependencies +----------------------- + +* The :ref:`Ninja Generators` now support generating a build target named + ``test_prep/<test-name>`` for each test added by :command:`add_test`, which + builds all dependencies for that test. Build dependencies are registered for + an executable target invoked by the test, targets referenced in generator + expressions in the test command, and explicit dependencies added using the + new ``BUILD_DEPENDS`` option. This behavior is enabled by the new + :variable:`CMAKE_TEST_BUILD_DEPENDS` variable. A ``test_prep/all`` + target is also generated to depend on every ``test_prep/<test-name>`` + target. Tests with names that are not valid target names are excluded from + this behavior. If multiple tests in different directories share the same + name, their dependencies are merged into one ``test_prep/<test-name>`` + target.
diff --git a/Help/variable/CMAKE_TEST_BUILD_DEPENDS.rst b/Help/variable/CMAKE_TEST_BUILD_DEPENDS.rst new file mode 100644 index 0000000..cdc5b18 --- /dev/null +++ b/Help/variable/CMAKE_TEST_BUILD_DEPENDS.rst
@@ -0,0 +1,17 @@ +CMAKE_TEST_BUILD_DEPENDS +------------------------ + +.. versionadded:: 4.4 + +Enable ``test_prep/<name>`` build targets for tests added by +:command:`add_test` when using the :ref:`Ninja Generators`. + +When this variable is set to a true value, CMake generates a +``test_prep/<name>`` target for each eligible test and a ``test_prep/all`` +target for all such tests. Building these targets ensures the test executable, +targets referenced by test command generator expressions, and explicit +``BUILD_DEPENDS`` entries are up-to-date before the test runs. + +Tests whose names are not valid target names are excluded from this behavior. +If multiple tests in different directories share the same name, their +dependencies are merged into a single ``test_prep/<name>`` target.
diff --git a/Help/variable/CTEST_BUILD_PRESET.rst b/Help/variable/CTEST_BUILD_PRESET.rst new file mode 100644 index 0000000..8803b3f --- /dev/null +++ b/Help/variable/CTEST_BUILD_PRESET.rst
@@ -0,0 +1,10 @@ +CTEST_BUILD_PRESET +------------------ + +.. versionadded:: 4.4 + +Specify the ``PRESET`` option for the :command:`ctest_build` command +in a :manual:`ctest(1)` :ref:`Dashboard Client` script, +or on the :program:`ctest` command line via the :ref:`-D <ctest-option-D-var>` option. + +See also :variable:`CTEST_PRESET` and :variable:`CTEST_PRESETS_FILE`.
diff --git a/Help/variable/CTEST_CONFIGURE_PRESET.rst b/Help/variable/CTEST_CONFIGURE_PRESET.rst new file mode 100644 index 0000000..58028bc --- /dev/null +++ b/Help/variable/CTEST_CONFIGURE_PRESET.rst
@@ -0,0 +1,10 @@ +CTEST_CONFIGURE_PRESET +---------------------- + +.. versionadded:: 4.4 + +Specify the ``PRESET`` option for the :command:`ctest_configure` command +in a :manual:`ctest(1)` :ref:`Dashboard Client` script, +or on the :program:`ctest` command line via the :ref:`-D <ctest-option-D-var>` option. + +See also :variable:`CTEST_PRESET` and :variable:`CTEST_PRESETS_FILE`.
diff --git a/Help/variable/CTEST_PRESET.rst b/Help/variable/CTEST_PRESET.rst new file mode 100644 index 0000000..a08ea55 --- /dev/null +++ b/Help/variable/CTEST_PRESET.rst
@@ -0,0 +1,22 @@ +CTEST_PRESET +------------ + +.. versionadded:: 4.4 + +Specify a preset name to use for all relevant :manual:`ctest(1)` +:ref:`Dashboard Client` steps in a dashboard script, +or on the :program:`ctest` command line via the :ref:`-D <ctest-option-D-var>` option. + +This variable sets the ``PRESET`` option for :command:`ctest_configure`, +:command:`ctest_build`, :command:`ctest_test`, and :command:`ctest_memcheck` +when those commands are not given an explicit ``PRESET`` argument and the +corresponding command-specific variable +(:variable:`CTEST_CONFIGURE_PRESET`, :variable:`CTEST_BUILD_PRESET`, or +:variable:`CTEST_TEST_PRESET`) is also unset. + +For :command:`ctest_configure`, an error is raised if no configure preset +with this name exists. For :command:`ctest_build`, :command:`ctest_test`, +and :command:`ctest_memcheck`, a warning is emitted and the variable is +ignored if no preset of the matching type exists with this name. + +See also :variable:`CTEST_PRESETS_FILE`.
diff --git a/Help/variable/CTEST_PRESETS_FILE.rst b/Help/variable/CTEST_PRESETS_FILE.rst new file mode 100644 index 0000000..3345d7e --- /dev/null +++ b/Help/variable/CTEST_PRESETS_FILE.rst
@@ -0,0 +1,16 @@ +CTEST_PRESETS_FILE +------------------ + +.. versionadded:: 4.4 + +Specify the ``PRESETS_FILE`` option for all relevant :manual:`ctest(1)` +:ref:`Dashboard Client` step commands in a dashboard script, +or on the :program:`ctest` command line via the :ref:`-D <ctest-option-D-var>` option. + +This variable sets the ``PRESETS_FILE`` option for +:command:`ctest_configure`, :command:`ctest_build`, :command:`ctest_test`, +and :command:`ctest_memcheck` when those commands are not given an explicit +``PRESETS_FILE`` argument. + +See also :variable:`CTEST_PRESET`, :variable:`CTEST_CONFIGURE_PRESET`, +:variable:`CTEST_BUILD_PRESET`, and :variable:`CTEST_TEST_PRESET`.
diff --git a/Help/variable/CTEST_TEST_PRESET.rst b/Help/variable/CTEST_TEST_PRESET.rst new file mode 100644 index 0000000..cbbfcf5 --- /dev/null +++ b/Help/variable/CTEST_TEST_PRESET.rst
@@ -0,0 +1,11 @@ +CTEST_TEST_PRESET +----------------- + +.. versionadded:: 4.4 + +Specify the ``PRESET`` option for the :command:`ctest_test` and +:command:`ctest_memcheck` commands in a :manual:`ctest(1)` +:ref:`Dashboard Client` script, +or on the :program:`ctest` command line via the :ref:`-D <ctest-option-D-var>` option. + +See also :variable:`CTEST_PRESET` and :variable:`CTEST_PRESETS_FILE`.
diff --git a/Modules/CMakeDetermineRustCompiler.cmake b/Modules/CMakeDetermineRustCompiler.cmake index 971354f..4272e1b 100644 --- a/Modules/CMakeDetermineRustCompiler.cmake +++ b/Modules/CMakeDetermineRustCompiler.cmake
@@ -3,7 +3,7 @@ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) -if(NOT "${CMAKE_GENERATOR}" MATCHES "^Ninja") +if(NOT "${CMAKE_GENERATOR}" MATCHES "^(Ninja)|(Unix Makefiles)") message(FATAL_ERROR "Rust language not supported by \"${CMAKE_GENERATOR}\" generator") endif()
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 12d5f3b..6cec11a 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake
@@ -258,7 +258,7 @@ :command:`FetchContent_Declare` for each dependency, and the first such call will control how that dependency will be made available, as described below. - If ``<lowercaseName>_SOURCE_DIR`` is not set: + If ``FETCHCONTENT_SOURCE_DIR_<uppercaseName>`` is not set: * .. versionadded:: 3.24
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f6be1e2..7f2cf52 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 4) set(CMake_VERSION_MINOR 3) -set(CMake_VERSION_PATCH 20260527) +set(CMake_VERSION_PATCH 20260528) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 1000d6e..70ffdba 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -73,18 +73,54 @@ ? args.Target : mf.GetSafeDefinition("CTEST_BUILD_TARGET"); + // Preset name is set according to the following priority order: + // 1) The PRESET option to ctest_build() + // 2) CTEST_BUILD_PRESET script variable + // 3) CTEST_PRESET script variable (a warning is emitted if no build preset + // exists with this name) + std::string const sourceDirectory = + mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); + + // Presets file is set according to the following priority order: + // 1) The PRESETS_FILE option to ctest_build() + // 2) CTEST_PRESETS_FILE script variable + std::string const rawPresetsFile = !args.PresetsFile.empty() + ? args.PresetsFile + : mf.GetSafeDefinition("CTEST_PRESETS_FILE"); + + std::string const presetsFile = rawPresetsFile.empty() + ? "" + : cmSystemTools::CollapseFullPath(rawPresetsFile, sourceDirectory); + + std::string effectivePreset = !args.Preset.empty() ? args.Preset + : cmNonempty(mf.GetDefinition("CTEST_BUILD_PRESET")) + ? *mf.GetDefinition("CTEST_BUILD_PRESET") + : ""; + if (effectivePreset.empty()) { + cmValue v = mf.GetDefinition("CTEST_PRESET"); + if (cmNonempty(v)) { + std::string presetError; + auto presetCheck = + BuildPresetExists(*v, sourceDirectory, presetsFile, presetError); + if (presetCheck == PresetCheckResult::ReadError) { + status.SetError(cmStrCat('\n', presetError)); + return nullptr; + } + if (presetCheck == PresetCheckResult::Found) { + effectivePreset = *v; + } else { + cmCTestLog(this->CTest, WARNING, + "No build preset named \"" + << *v << "\" found, ignoring CTEST_PRESET." << std::endl); + } + } + } + cmValue ctestBuildCommand = mf.GetDefinition("CTEST_BUILD_COMMAND"); if (cmNonempty(ctestBuildCommand)) { this->CTest->SetCTestConfiguration("MakeCommand", *ctestBuildCommand, args.Quiet); - } else if (!args.Preset.empty()) { - std::string const sourceDirectory = - mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); - - std::string const presetsFile = args.PresetsFile.empty() - ? "" - : cmSystemTools::CollapseFullPath(args.PresetsFile, sourceDirectory); - + } else if (!effectivePreset.empty()) { cmCMakePresetsGraph presetsGraph; if (!presetsGraph.ReadProjectPresets(sourceDirectory, presetsFile)) { status.SetError(cmStrCat("\n Could not read presets from \"", @@ -94,7 +130,7 @@ } auto resolveResult = - presetsGraph.ResolvePreset(args.Preset, presetsGraph.BuildPresets); + presetsGraph.ResolvePreset(effectivePreset, presetsGraph.BuildPresets); auto resolveError = cmCMakePresetsGraph::FormatPresetError<BuildPreset>( resolveResult.StatusCode, resolveResult.ErrorPresetName, sourceDirectory); @@ -106,7 +142,7 @@ std::string buildCommand = cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"'); buildCommand += " --build . --preset \""; - buildCommand += args.Preset; + buildCommand += effectivePreset; buildCommand += "\""; if (!presetsFile.empty()) {
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index 1f76abc..ac24e90 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -191,14 +191,30 @@ return false; } - std::string const presetsFile = args.PresetsFile.empty() + // Preset name is set according to the following priority order: + // 1) The PRESET option to ctest_configure() + // 2) CTEST_CONFIGURE_PRESET script variable + // 3) CTEST_PRESET script variable (error if no such configure preset exists) + std::string const presetName = !args.Preset.empty() ? args.Preset + : cmNonempty(mf.GetDefinition("CTEST_CONFIGURE_PRESET")) + ? *mf.GetDefinition("CTEST_CONFIGURE_PRESET") + : mf.GetSafeDefinition("CTEST_PRESET"); + + // Presets file is set according to the following priority order: + // 1) The PRESETS_FILE option to ctest_configure() + // 2) CTEST_PRESETS_FILE script variable + std::string const rawPresetsFile = !args.PresetsFile.empty() + ? args.PresetsFile + : mf.GetSafeDefinition("CTEST_PRESETS_FILE"); + + std::string const presetsFile = rawPresetsFile.empty() ? "" - : cmSystemTools::CollapseFullPath(args.PresetsFile, sourceDirectory); + : cmSystemTools::CollapseFullPath(rawPresetsFile, sourceDirectory); std::string configureCommand = mf.GetDefinition("CTEST_CONFIGURE_COMMAND"); if (configureCommand.empty() && !ConstructConfigureCommand(status, mf, sourceDirectory, buildDirectory, - args.Options, args.Preset, presetsFile, + args.Options, presetName, presetsFile, configureCommand)) { return false; }
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index b8e6a03..a85386e 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -8,9 +8,11 @@ #include <cm/string_view> +#include "cmCMakePresetsGraph.h" #include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmExecutionStatus.h" +#include "cmJSONState.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -216,3 +218,55 @@ cmExecutionStatus&) const { } + +namespace { +enum class PresetType +{ + Build, + Test, +}; + +cmCTestHandlerCommand::PresetCheckResult PresetExistsInGraph( + cmCMakePresetsGraph& graph, std::string const& name, + std::string const& sourceDir, std::string const& presetsFile, + PresetType presetType, std::string& errorMessage) +{ + using Result = cmCTestHandlerCommand::PresetCheckResult; + if (!graph.ReadProjectPresets(sourceDir, presetsFile)) { + errorMessage = cmStrCat("Could not read presets from \"", sourceDir, + "\":\n ", graph.parseState.GetErrorMessage()); + return Result::ReadError; + } + using Status = cmCMakePresetsGraph::PresetResolveStatus; + if (presetType == PresetType::Build) { + auto result = graph.ResolvePreset(name, graph.BuildPresets); + return result.StatusCode == Status::Success ? Result::Found + : Result::NotFound; + } + auto result = graph.ResolvePreset(name, graph.TestPresets); + return result.StatusCode == Status::Success ? Result::Found + : Result::NotFound; +} +} + +cmCTestHandlerCommand::PresetCheckResult +cmCTestHandlerCommand::BuildPresetExists(std::string const& name, + std::string const& sourceDir, + std::string const& presetsFile, + std::string& errorMessage) +{ + cmCMakePresetsGraph graph; + return PresetExistsInGraph(graph, name, sourceDir, presetsFile, + PresetType::Build, errorMessage); +} + +cmCTestHandlerCommand::PresetCheckResult +cmCTestHandlerCommand::TestPresetExists(std::string const& name, + std::string const& sourceDir, + std::string const& presetsFile, + std::string& errorMessage) +{ + cmCMakePresetsGraph graph; + return PresetExistsInGraph(graph, name, sourceDir, presetsFile, + PresetType::Test, errorMessage); +}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index ef7bc5d..4b5111b 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -24,6 +24,13 @@ public: using cmCTestCommand::cmCTestCommand; + enum class PresetCheckResult + { + Found, + NotFound, + ReadError, + }; + protected: struct BasicArguments : ArgumentParser::ParseResult { @@ -78,6 +85,15 @@ bool ExecuteHandlerCommand(HandlerArguments& args, cmExecutionStatus& status) const; + static PresetCheckResult BuildPresetExists(std::string const& name, + std::string const& sourceDir, + std::string const& presetsFile, + std::string& errorMessage); + static PresetCheckResult TestPresetExists(std::string const& name, + std::string const& sourceDir, + std::string const& presetsFile, + std::string& errorMessage); + private: bool InvokeImpl(BasicArguments& args, std::vector<std::string> const& unparsed,
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 41df2b5..3e8e319 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -34,16 +34,52 @@ cmMakefile& mf = status.GetMakefile(); auto& args = static_cast<TestArguments&>(arguments); + std::string const sourceDirectory = + mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); + + // Presets file is set according to the following priority order: + // 1) The PRESETS_FILE option to ctest_test() + // 2) CTEST_PRESETS_FILE script variable + std::string const rawPresetsFile = !args.PresetsFile.empty() + ? args.PresetsFile + : mf.GetSafeDefinition("CTEST_PRESETS_FILE"); + + std::string const presetsFile = rawPresetsFile.empty() + ? "" + : cmSystemTools::CollapseFullPath(rawPresetsFile, sourceDirectory); + + // Preset name is set according to the following priority order: + // 1) The PRESET option to ctest_test() + // 2) CTEST_TEST_PRESET script variable + // 3) CTEST_PRESET script variable (a warning is emitted if no test preset + // exists with this name) + std::string effectivePreset = !args.Preset.empty() ? args.Preset + : cmNonempty(mf.GetDefinition("CTEST_TEST_PRESET")) + ? *mf.GetDefinition("CTEST_TEST_PRESET") + : ""; + if (effectivePreset.empty()) { + cmValue v = mf.GetDefinition("CTEST_PRESET"); + if (cmNonempty(v)) { + std::string presetError; + auto presetCheck = + TestPresetExists(*v, sourceDirectory, presetsFile, presetError); + if (presetCheck == PresetCheckResult::ReadError) { + status.SetError(cmStrCat('\n', presetError)); + return nullptr; + } + if (presetCheck == PresetCheckResult::Found) { + effectivePreset = *v; + } else { + cmCTestLog(this->CTest, WARNING, + "No test preset named \"" + << *v << "\" found, ignoring CTEST_PRESET." << std::endl); + } + } + } + std::unique_ptr<cmCMakePresetsGraph> presetsGraph; TestPreset const* expandedPreset = nullptr; - if (!args.Preset.empty()) { - std::string const sourceDirectory = - mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); - - std::string const presetsFile = args.PresetsFile.empty() - ? "" - : cmSystemTools::CollapseFullPath(args.PresetsFile, sourceDirectory); - + if (!effectivePreset.empty()) { presetsGraph = cm::make_unique<cmCMakePresetsGraph>(); if (!presetsGraph->ReadProjectPresets(sourceDirectory, presetsFile)) { status.SetError(cmStrCat("\n Could not read presets from \"", @@ -53,7 +89,7 @@ } auto resolveResult = - presetsGraph->ResolvePreset(args.Preset, presetsGraph->TestPresets); + presetsGraph->ResolvePreset(effectivePreset, presetsGraph->TestPresets); auto resolveError = cmCMakePresetsGraph::FormatPresetError<TestPreset>( resolveResult.StatusCode, resolveResult.ErrorPresetName, sourceDirectory);
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index f2579e3..5663eaf 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx
@@ -7,6 +7,7 @@ #include <cm/memory> #include "cmExecutionStatus.h" +#include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmStringAlgorithms.h" @@ -90,6 +91,7 @@ std::vector<std::string> configurations; std::string working_directory; std::vector<std::string> command; + std::vector<std::string> buildDepends; bool command_expand_lists = false; cmPolicies::PolicyStatus cmp0178 = mf.GetPolicyStatus(cmPolicies::CMP0178); @@ -100,6 +102,7 @@ DoingCommand, DoingConfigs, DoingWorkingDirectory, + DoingBuildDepends, DoingCmp0178, DoingNone }; @@ -117,6 +120,8 @@ return false; } doing = DoingConfigs; + } else if (args[i] == "BUILD_DEPENDS") { + doing = DoingBuildDepends; } else if (args[i] == "WORKING_DIRECTORY") { if (!working_directory.empty()) { status.SetError(" may be given at most one WORKING_DIRECTORY."); @@ -139,6 +144,8 @@ command.push_back(args[i]); } else if (doing == DoingConfigs) { configurations.push_back(args[i]); + } else if (doing == DoingBuildDepends) { + buildDepends.push_back(args[i]); } else if (doing == DoingWorkingDirectory) { working_directory = args[i]; doing = DoingNone; @@ -185,6 +192,15 @@ test->SetProperty("WORKING_DIRECTORY", working_directory); } test->SetCommandExpandLists(command_expand_lists); + if (!buildDepends.empty()) { + if (!cmGeneratorExpression::IsValidTargetName(name)) { + status.SetError(cmStrCat("Cannot set build dependencies for a test with" + " NAME \"", + name, "\" which is not a valid target name.")); + return false; + } + test->SetBuildDependencies(buildDepends); + } mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test, configurations)); return true;
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 6db6767..f873769 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx
@@ -6,6 +6,7 @@ #include <sstream> #include <utility> +#include <cm/filesystem> #include <cm/string_view> #include <cmext/string_view> @@ -653,3 +654,34 @@ }; return std::all_of(languagesNeeded.cbegin(), languagesNeeded.cend(), unary); } + +void cmCommonTargetGenerator::ComputeRustFlagsForObjects( + std::string& linkCrates, std::string& nativeObjects, + std::vector<std::string> const& objects) +{ + std::stringstream rlibsArgs; + std::stringstream objectsArgs; + auto const processObject = [&](std::string const& obj) { + cm::filesystem::path const objPath(obj); + if (objPath.extension() == ".rlib") { + // Drop the "lib..." prefix and the ".rs" suffix. The prefix is required + // by Rust on the crate rlib file, but is hidden from the user when using + // the crate from Rust source code, so we drop it to be consistent with + // common usage in Rust. + std::string objStem = objPath.stem().string(); + objStem = objStem.substr(3, objStem.length() - 6); + rlibsArgs << " --extern=" << objStem << "=" + << this->LocalCommonGenerator->ConvertToOutputFormat( + obj, cmOutputConverter::SHELL); + } else { + objectsArgs << " -Clink-arg=" + << this->LocalCommonGenerator->ConvertToOutputFormat( + obj, cmOutputConverter::SHELL); + } + }; + for (auto const& obj : objects) { + processObject(obj); + } + linkCrates += rlibsArgs.str(); + nativeObjects += objectsArgs.str(); +}
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index b97b947..d8fd694 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h
@@ -90,6 +90,10 @@ bool HaveRequiredLanguages(std::vector<cmSourceFile const*> const& sources, std::set<std::string>& languagesNeeded) const; + void ComputeRustFlagsForObjects(std::string& linkCrates, + std::string& nativeObjects, + std::vector<std::string> const& objects); + private: using ByLanguageMap = std::map<std::string, std::string>; struct ByConfig
diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index 9c1f2f1..fa56531 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx
@@ -64,7 +64,7 @@ cmExperimental::TryCompileCondition::Never }, // Rust support { "Rust", - "efaed83b-d73a-48af-999a-bd0a6172c313", + "b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1", "CMAKE_EXPERIMENTAL_RUST", "CMake's support for the Rust programming language is experimental. " "It is meant only for experimentation and feedback to CMake developers.",
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d5b2422..366314c 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx
@@ -2180,7 +2180,16 @@ if (tlsVersionOpt.has_value()) { if (cm::optional<int> v = cmCurlParseTLSVersion(*tlsVersionOpt)) { res = ::curl_easy_setopt(curl, CURLOPT_SSLVERSION, *v); - if (tlsVersionDefaulted && res == CURLE_NOT_BUILT_IN) { + // If the caller did not explicitly ask for TLS, and libcurl was + // built without any TLS backend, ignore failure to set our default. + // Note that libcurl reports the absence of any TLS backend with + // one of two distinct errors depending on how it was built: + // - CURLE_NOT_BUILT_IN from the Curl_setopt_SSLVERSION + // stub macro in setopt.h, or + // - CURLE_UNKNOWN_OPTION from the function-level #else + // arm of setopt_long_ssl() in setopt.c. + if (tlsVersionDefaulted && + (res == CURLE_NOT_BUILT_IN || res == CURLE_UNKNOWN_OPTION)) { res = CURLE_OK; } check_curl_result(res, @@ -2583,7 +2592,10 @@ if (tlsVersionOpt.has_value()) { if (cm::optional<int> v = cmCurlParseTLSVersion(*tlsVersionOpt)) { res = ::curl_easy_setopt(curl, CURLOPT_SSLVERSION, *v); - if (tlsVersionDefaulted && res == CURLE_NOT_BUILT_IN) { + // See HandleDownloadCommand for the rationale behind accepting both + // CURLE_NOT_BUILT_IN and CURLE_UNKNOWN_OPTION here. + if (tlsVersionDefaulted && + (res == CURLE_NOT_BUILT_IN || res == CURLE_UNKNOWN_OPTION)) { res = CURLE_OK; } check_curl_result(
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d3d589a..0312da4 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx
@@ -1013,6 +1013,18 @@ IMPLEMENT_VISIT(SourceKindRustMainCrateRoot); } +cmSourceFile const* cmGeneratorTarget::GetRustMainCrateRoot( + std::string const& config) const +{ + std::vector<cmSourceFile const*> files; + GetRustMainCrateRoot(files, config); + if (files.empty()) { + return nullptr; + } + assert(files.size() == 1); + return files[0]; +} + std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const { if (!this->UtilityItemsDone) {
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 23f59bc..2889b39 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h
@@ -228,6 +228,8 @@ void GetRustMainCrateRoot(std::vector<cmSourceFile const*>&, std::string const& config) const; + cmSourceFile const* GetRustMainCrateRoot(std::string const& config) const; + std::set<cmLinkItem> const& GetUtilityItems() const; void ComputeObjectMapping();
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 70702ae..0525a81 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx
@@ -551,7 +551,7 @@ if (lang == "NONE") { this->SetLanguageEnabled("NONE", mf); } else { - if (!cm::contains(this->LanguagesReady, lang)) { + if (!cm::contains(this->LanguagesReadyForTryCompile, lang)) { std::ostringstream e; e << "The test project needs language " << lang << " which is not enabled."; @@ -905,12 +905,12 @@ if (needSetLanguageEnabledMaps[lang]) { this->SetLanguageEnabledMaps(lang, mf); } - this->LanguagesReady.insert(lang); + + // At this point we have enough info for a try compile. + this->LanguagesReadyForTryCompile.insert(lang); // Test the compiler for the language just setup // (but only if a compiler has been actually found) - // At this point we should have enough info for a try compile - // which is used in the backward stuff // If the language is untested then test it now with a try compile. if (needTestLanguage[lang]) { if (!this->CMakeInstance->GetIsInTryCompile()) { @@ -2566,8 +2566,7 @@ return cm::make_unique<cmLocalGenerator>(this, mf); } -void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen, - cmMakefile* mf) +void cmGlobalGenerator::SetupTryCompile(cmGlobalGenerator* gen, cmMakefile* mf) { this->SetConfiguredFilesPath(gen); this->TryCompileOuterMakefile = mf; @@ -2575,15 +2574,7 @@ gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); this->GetCMakeInstance()->AddCacheEntry( "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH); - // copy the enabled languages - this->GetCMakeInstance()->GetState()->SetEnabledLanguages( - gen->GetCMakeInstance()->GetState()->GetEnabledLanguages()); - this->LanguagesReady = gen->LanguagesReady; - this->ExtensionToLanguage = gen->ExtensionToLanguage; - this->IgnoreExtensions = gen->IgnoreExtensions; - this->LanguageToOutputExtension = gen->LanguageToOutputExtension; - this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference; - this->OutputExtensions = gen->OutputExtensions; + this->LanguagesReadyForTryCompile = gen->LanguagesReadyForTryCompile; } void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 3c11699..c402e66 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h
@@ -240,11 +240,7 @@ void ResolveLanguageCompiler(std::string const& lang, cmMakefile* mf, bool optional) const; - /** - * Try to determine system information, get it from another generator - */ - void EnableLanguagesFromGenerator(cmGlobalGenerator* gen, cmMakefile* mf); - + void SetupTryCompile(cmGlobalGenerator* gen, cmMakefile* mf); /** * Try running cmake and building a file. This is used for dynamically * loaded commands, not as part of the usual build process. @@ -870,10 +866,8 @@ std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex; cmMakefile* TryCompileOuterMakefile; - // If you add a new map here, make sure it is copied - // in EnableLanguagesFromGenerator std::map<std::string, bool> IgnoreExtensions; - std::set<std::string> LanguagesReady; // Ready for try_compile + std::set<std::string> LanguagesReadyForTryCompile; std::set<std::string> LanguagesInProgress; std::map<std::string, std::string> OutputExtensions; std::map<std::string, std::string> LanguageToOutputExtension;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 23c7ef4..8d29ec4 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -54,6 +54,8 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" +#include "cmTest.h" +#include "cmTestGenerator.h" #include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -641,6 +643,7 @@ this->cmGlobalGenerator::Generate(); this->WriteAssumedSourceDependencies(); + this->WriteTestPrepTargets(); this->WriteTargetAliases(*this->GetCommonFileStream()); this->WriteFolderTargets(*this->GetCommonFileStream()); this->WriteBuiltinTargets(*this->GetCommonFileStream()); @@ -1293,6 +1296,80 @@ } } +void cmGlobalNinjaGenerator::WriteTestPrepTargets() +{ + auto writeConfig = [this](std::string const& config, std::ostream& os) { + struct TestPrepTarget + { + std::string Comment; + cmNinjaDeps ExplicitDeps; + }; + + std::map<std::string, TestPrepTarget> testPrepTargets; + for (auto const& localGen : this->LocalGenerators) { + auto* lg = static_cast<cmLocalNinjaGenerator*>(localGen.get()); + auto const& testGenerators = lg->GetMakefile()->GetTestGenerators(); + for (auto const& tester : testGenerators) { + cmTestGenerator::BuildDependencies testDeps; + if (!tester->GetBuildDependencies(lg, testDeps)) { + continue; + } + std::string const depName = this->ConvertToNinjaPath( + cmStrCat("test_prep/", tester->GetTest()->GetName())); + // Merge with existing target if multiple tests have the same name + auto& testPrepTarget = testPrepTargets[depName]; + testPrepTarget.Comment = cmStrCat("Build dependencies for test ", + tester->GetTest()->GetName()); + + for (cmGeneratorTarget* depTarget : testDeps.Targets) { + this->AppendTargetOutputs(depTarget, testPrepTarget.ExplicitDeps, + config, DependOnTargetArtifact); + } + std::transform(testDeps.Files.begin(), testDeps.Files.end(), + std::back_inserter(testPrepTarget.ExplicitDeps), + this->MapToNinjaPath()); + } + } + + std::vector<std::string> allDeps; + for (auto& prepTarget : testPrepTargets) { + cmNinjaBuild build("phony"); + build.Comment = prepTarget.second.Comment; + build.Outputs.push_back(prepTarget.first); + + // Avoid duplicate dependencies when merging test_prep/ targets + auto& explicitDeps = prepTarget.second.ExplicitDeps; + std::sort(explicitDeps.begin(), explicitDeps.end()); + explicitDeps.erase(std::unique(explicitDeps.begin(), explicitDeps.end()), + explicitDeps.end()); + build.ExplicitDeps = std::move(explicitDeps); + + allDeps.push_back(prepTarget.first); + this->WriteBuild(os, build); + } + + cmNinjaBuild build("phony"); + build.Comment = "Build dependencies for all tests"; + build.Outputs.push_back(this->ConvertToNinjaPath("test_prep/all")); + build.ExplicitDeps = std::move(allDeps); + this->WriteBuild(os, build); + return true; + }; + + if (!this->Makefiles.front()->IsOn("CMAKE_TEST_BUILD_DEPENDS")) { + return; + } + if (this->IsMultiConfig()) { + for (std::string const& config : this->GetConfigNames()) { + if (!writeConfig(config, *this->GetConfigFileStream(config))) { + return; + } + } + } else { + writeConfig(std::string(), *this->GetCommonFileStream()); + } +} + std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( cmGeneratorTarget const* target, std::string const& /*config*/) const {
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 059dea8..7ade62a 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h
@@ -524,6 +524,7 @@ void WriteDisclaimer(std::ostream& os) const; void WriteAssumedSourceDependencies(); + void WriteTestPrepTargets(); void WriteTargetAliases(std::ostream& os); void WriteFolderTargets(std::ostream& os);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 40e9534..0a58f06 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -930,7 +930,6 @@ this->FileRefs.clear(); this->ExternalLibRefs.clear(); this->FileRefToBuildFileMap.clear(); - this->FileRefToEmbedBuildFileMap.clear(); this->CommandsVisited.clear(); } @@ -4428,14 +4427,9 @@ " is missing product reference")); continue; } - auto it = this->FileRefToEmbedBuildFileMap.find(fileRefObject); - if (it == this->FileRefToEmbedBuildFileMap.end()) { - buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); - buildFile->AddAttribute("fileRef", fileRefObject); - this->FileRefToEmbedBuildFileMap[fileRefObject] = buildFile; - } else { - buildFile = it->second; - } + buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); + buildFile->SetComment(xcTarget->GetComment()); + buildFile->AddAttribute("fileRef", fileRefObject); } else if (cmSystemTools::IsPathToFramework(relFile) || cmSystemTools::IsPathToMacOSSharedLibrary(relFile) || cmSystemTools::FileIsDirectory(filePath)) {
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 114caec..908dc7b 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h
@@ -381,7 +381,6 @@ std::map<std::string, cmXCodeObject*> ExternalLibRefs; std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap; std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap; - std::map<cmXCodeObject*, cmXCodeObject*> FileRefToEmbedBuildFileMap; std::vector<std::string> Architectures; std::string ObjectDirArchDefault; std::string ObjectDirArch;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 490c5d6..9b9a3f8 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx
@@ -3366,8 +3366,7 @@ cm.SetCacheArgs(*cmakeArgs); } // to save time we pass the EnableLanguage info directly - cm.GetGlobalGenerator()->EnableLanguagesFromGenerator( - this->GetGlobalGenerator(), this); + cm.GetGlobalGenerator()->SetupTryCompile(this->GetGlobalGenerator(), this); for (unsigned dc = 1; dc < cmDiagnostics::CategoryCount; ++dc) { auto const category = static_cast<cmDiagnosticCategory>(dc); if (this->GetDiagnosticAction(category) == cmDiagnostics::Ignore) {
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 453fbe2..77c040f 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -598,6 +598,16 @@ vars.Launcher = linkerLauncher.c_str(); } + std::string rustMainCrateRootPath; + std::string rustLinkCrates; + std::string rustNativeObjects; + if (CreateRustLinkArguments(linkLanguage, rustMainCrateRootPath, + rustLinkCrates, rustNativeObjects)) { + vars.RustMainCrateRoot = rustMainCrateRootPath.c_str(); + vars.RustLinkCrates = rustLinkCrates.c_str(); + vars.RustNativeObjects = rustNativeObjects.c_str(); + } + if (this->UseLWYU) { cmValue lwyuCheck = this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index c046e11..d04051c 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -837,6 +837,16 @@ vars.Manifests = manifests.c_str(); vars.Config = this->GetConfigName().c_str(); + std::string rustMainCrateRootPath; + std::string rustLinkCrates; + std::string rustNativeObjects; + if (CreateRustLinkArguments(linkLanguage, rustMainCrateRootPath, + rustLinkCrates, rustNativeObjects)) { + vars.RustMainCrateRoot = rustMainCrateRootPath.c_str(); + vars.RustLinkCrates = rustLinkCrates.c_str(); + vars.RustNativeObjects = rustNativeObjects.c_str(); + } + // Compute the directory portion of the install_name setting. std::string install_name_dir; if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY) {
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 59c0519..2260041 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx
@@ -976,6 +976,7 @@ vars.Flags = flags.c_str(); vars.ISPCHeader = ispcHeaderForShell.c_str(); vars.Config = this->GetConfigName().c_str(); + vars.RustEmit = source.GetRustEmitProperty()->c_str(); std::string definesString = cmStrCat("$(", lang, "_DEFINES)"); @@ -2053,6 +2054,12 @@ // Add dependencies on the external object files. cm::append(depends, this->ExternalObjects); + // Add dependency on the Rust main crate root file. + if (cmSourceFile const* mainCrateRoot = + this->GeneratorTarget->GetRustMainCrateRoot(this->GetConfigName())) { + depends.push_back(mainCrateRoot->GetFullPath()); + } + // Add a dependency on the rule file itself. this->LocalGenerator->AppendRuleDepend(depends, this->BuildFileNameFull.c_str()); @@ -2326,6 +2333,33 @@ } } +bool cmMakefileTargetGenerator::CreateRustLinkArguments( + std::string const& linkLanguage, std::string& rustMainCrateRootPath, + std::string& rustLinkCrates, std::string& rustNativeObjects) +{ + if (linkLanguage == "Rust") { + this->ComputeRustFlagsForObjects(rustLinkCrates, rustNativeObjects, + this->Objects); + this->ComputeRustFlagsForObjects(rustLinkCrates, rustNativeObjects, + this->ExternalObjects); + + cmSourceFile const* mainCrateRoot = + this->GeneratorTarget->GetRustMainCrateRoot(this->GetConfigName()); + if (!mainCrateRoot) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "Target " + + this->GeneratorTarget->GetName() + + " has no main crate root."); + return false; + } + rustMainCrateRootPath = mainCrateRoot->GetFullPath(); + rustMainCrateRootPath = this->LocalGenerator->ConvertToOutputFormat( + rustMainCrateRootPath, cmOutputConverter::SHELL); + return true; + } + return false; +} + void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::string const& lang, std::string const& /*config*/)
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index bcb5f26..ce78230 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h
@@ -193,6 +193,11 @@ bool useWatcomQuote, std::string const& linkLanguage, ResponseFlagFor responseMode = ResponseFlagFor::Link); + bool CreateRustLinkArguments(std::string const& linkLanguage, + std::string& rustMainCrateRootPath, + std::string& rustLinkCrates, + std::string& rustNativeObjects); + /** Add commands for generate def files */ void GenDefFile(std::vector<std::string>& real_link_commands);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 7ff9bb2..3fbc178 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -10,7 +10,6 @@ #include <unordered_set> #include <utility> -#include <cm/filesystem> #include <cm/memory> #include <cm/optional> #include <cm/vector> @@ -1299,40 +1298,21 @@ linkBuild.ExplicitDeps = this->GetObjects(config); // First we handle Rust rlib and normal native objects. - std::stringstream rlibs; - std::stringstream objects; - for (auto const& obj : linkBuild.ExplicitDeps) { - cm::filesystem::path const objPath(obj); - if (objPath.extension() == ".rlib") { - // Drop the "lib..." prefix and the ".rs" suffix. The prefix is - // required by Rust on the crate rlib file, but is hidden from the user - // when using the crate from Rust source code, so we drop it to be - // consistent with common usage in Rust. - std::string objStem = objPath.stem().string(); - objStem = objStem.substr(3, objStem.length() - 6); - rlibs << " --extern=" << objStem << "=" - << lg->ConvertToOutputFormat(obj, cmOutputConverter::SHELL); - } else { - objects << " -Clink-arg=" - << lg->ConvertToOutputFormat(obj, cmOutputConverter::SHELL); - } - } - vars["RUST_LINK_CRATES"] = rlibs.str(); - vars["RUST_NATIVE_OBJECTS"] = objects.str(); + this->ComputeRustFlagsForObjects(vars["RUST_LINK_CRATES"], + vars["RUST_NATIVE_OBJECTS"], + linkBuild.ExplicitDeps); // Then, we handle the main crate root that is build as part of the link // step. - std::vector<cmSourceFile const*> mainCrateRoot; - gt->GetRustMainCrateRoot(mainCrateRoot, config); - if (mainCrateRoot.size() != 1) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "Target " + gt->GetName() + - " has none or more than one main crate root."); + cmSourceFile const* mainCrateRoot = gt->GetRustMainCrateRoot(config); + if (!mainCrateRoot) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "Target " + gt->GetName() + + " has no main crate root."); return; } std::string mainCrateRootPath = - this->GetCompiledSourceNinjaPath(mainCrateRoot[0]); + this->GetCompiledSourceNinjaPath(mainCrateRoot); linkBuild.ExplicitDeps.emplace_back(mainCrateRootPath); mainCrateRootPath = lg->ConvertToOutputFormat(mainCrateRootPath, cmOutputConverter::SHELL);
diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 7e86f08..038fdde 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx
@@ -390,11 +390,6 @@ return this->EnabledLanguages; } -void cmState::SetEnabledLanguages(std::vector<std::string> const& langs) -{ - this->EnabledLanguages = langs; -} - void cmState::ClearEnabledLanguages() { this->EnabledLanguages.clear();
diff --git a/Source/cmState.h b/Source/cmState.h index 5d8a1e7..9ed91f5 100644 --- a/Source/cmState.h +++ b/Source/cmState.h
@@ -159,7 +159,6 @@ void SetLanguageEnabled(std::string const& l); bool GetLanguageEnabled(std::string const& l) const; std::vector<std::string> GetEnabledLanguages() const; - void SetEnabledLanguages(std::vector<std::string> const& langs); void ClearEnabledLanguages(); bool GetIsGeneratorMultiConfig() const;
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 1620b46..75a81b8 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx
@@ -2,6 +2,8 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmTest.h" +#include <utility> + #include "cmMakefile.h" #include "cmProperty.h" #include "cmState.h" @@ -33,6 +35,11 @@ this->Command = command; } +void cmTest::SetBuildDependencies(std::vector<std::string> deps) +{ + this->BuildDependencies = std::move(deps); +} + cmValue cmTest::GetProperty(std::string const& prop) const { cmValue retVal = this->Properties.GetPropertyValue(prop);
diff --git a/Source/cmTest.h b/Source/cmTest.h index 7d347a8..ee7d935 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h
@@ -35,6 +35,12 @@ void SetCommand(std::vector<std::string> const& command); std::vector<std::string> const& GetCommand() const { return this->Command; } + void SetBuildDependencies(std::vector<std::string> deps); + std::vector<std::string> const& GetDependencies() const + { + return this->BuildDependencies; + } + //! Set/Get a property of this source file void SetProperty(std::string const& prop, cmValue value); void SetProperty(std::string const& prop, std::nullptr_t) @@ -85,6 +91,7 @@ cmPropertyMap Properties; std::string Name; std::vector<std::string> Command; + std::vector<std::string> BuildDependencies; bool CommandExpandLists = false; bool OldStyle;
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index f4fcfbb..5255023 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx
@@ -5,16 +5,19 @@ #include <cstddef> // IWYU pragma: keep #include <memory> #include <ostream> +#include <set> #include <string> #include <utility> #include <vector> #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" #include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmPropertyMap.h" #include "cmRange.h" @@ -90,6 +93,67 @@ return this->Test; } +bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg, + BuildDependencies& info) +{ + if (this->Test == nullptr || + !cmGeneratorExpression::IsValidTargetName(this->Test->GetName()) || + cmGlobalGenerator::IsReservedTarget(this->Test->GetName())) { + return false; + } + + std::set<cmGeneratorTarget*> dependencies; + + // Get dependencies from generator expressions + cmGeneratorExpression ge(*this->Test->GetMakefile()->GetCMakeInstance(), + this->Test->GetBacktrace()); + std::string const config; + for (std::string const& arg : this->Test->GetCommand()) { + auto parsed = ge.Parse(arg); + parsed->Evaluate(lg, config); + for (cmGeneratorTarget* dep : parsed->GetTargets()) { + if (dep && !dep->IsImported()) { + dependencies.insert(dep); + } + } + } + + // Add target executed by test + if (!this->Test->GetCommand().empty()) { + std::string exe = this->Test->GetCommand().front(); + cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(exe); + if (target && target->GetType() == cmStateEnums::EXECUTABLE && + !target->IsImported()) { + dependencies.insert(target); + } + } + + // Add dependencies from BUILD_DEPENDS keyword + for (auto const& depName : this->Test->GetDependencies()) { + if (depName.empty()) { + continue; + } + cmGeneratorTarget* depTarget = lg->FindGeneratorTargetToUse(depName); + if (!depTarget) { + info.Files.push_back(depName); + continue; + } + if (depTarget->IsImported()) { + lg->GetMakefile()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Test \"", this->Test->GetName(), "\" DEPENDS target \"", + depName, "\" which is imported and cannot be built."), + this->Test->GetBacktrace()); + return false; + } + dependencies.insert(depTarget); + } + + info.Targets.insert(info.Targets.end(), dependencies.begin(), + dependencies.end()); + return true; +} + void cmTestGenerator::GenerateScriptActions(std::ostream& os, Indent indent) { if (this->ActionsPerConfig) {
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index cd59b11..fe65a54 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h
@@ -13,6 +13,7 @@ class cmListFileBacktrace; class cmGeneratorExpression; +class cmGeneratorTarget; class cmLocalGenerator; class cmTest; @@ -23,6 +24,12 @@ class cmTestGenerator : public cmScriptGenerator { public: + struct BuildDependencies + { + std::vector<cmGeneratorTarget*> Targets; + std::vector<std::string> Files; + }; + cmTestGenerator(cmTest* test, std::vector<std::string> const& configurations = std::vector<std::string>()); @@ -32,6 +39,7 @@ cmTestGenerator& operator=(cmTestGenerator const&) = delete; void Compute(cmLocalGenerator* lg); + bool GetBuildDependencies(cmLocalGenerator* lg, BuildDependencies& deps); /** Test if this generator installs the test for a given configuration. */ bool TestsForConfig(std::string const& config);
diff --git a/Tests/RunCMake/CheckSourceCompiles/MultipleLanguages.cmake b/Tests/RunCMake/CheckSourceCompiles/MultipleLanguages.cmake new file mode 100644 index 0000000..5596040 --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/MultipleLanguages.cmake
@@ -0,0 +1,11 @@ +enable_language (C CXX) +include(CheckSourceCompiles) + +add_library(cxx_iface INTERFACE IMPORTED) +target_compile_features(cxx_iface INTERFACE cxx_std_11) +set(CMAKE_REQUIRED_LIBRARIES cxx_iface) + +check_source_compiles(C "int main() {return 0;}" SHOULD_BUILD) +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid C source.") +endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake index 2ed3e36..afee71e 100644 --- a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
@@ -3,6 +3,7 @@ run_cmake(NotEnabledLanguage) run_cmake(NonExistentLanguage) run_cmake(UnknownArgument) +run_cmake(MultipleLanguages) run_cmake(CheckCSourceCompiles) run_cmake(CheckCXXSourceCompiles)
diff --git a/Tests/RunCMake/Rust/Editions-build-stdout.txt b/Tests/RunCMake/Rust/Editions-build-Ninja-stdout.txt similarity index 100% rename from Tests/RunCMake/Rust/Editions-build-stdout.txt rename to Tests/RunCMake/Rust/Editions-build-Ninja-stdout.txt
diff --git a/Tests/RunCMake/Rust/Editions-build-UnixMakefiles-stdout.txt b/Tests/RunCMake/Rust/Editions-build-UnixMakefiles-stdout.txt new file mode 100644 index 0000000..a946b1e --- /dev/null +++ b/Tests/RunCMake/Rust/Editions-build-UnixMakefiles-stdout.txt
@@ -0,0 +1,10 @@ +\[ 20%\] Building Rust object CMakeFiles[\\/]Edition.20[0-9][0-9]\.dir[\\/]libedition_20[0-9][0-9]\.rs\.rlib +\[ 20%\] Built target Edition\.20[0-9][0-9] +\[ 40%\] Building Rust object CMakeFiles[\\/]Edition.20[0-9][0-9]\.dir[\\/]libedition_20[0-9][0-9]\.rs\.rlib +\[ 40%\] Built target Edition\.20[0-9][0-9] +\[ 60%\] Building Rust object CMakeFiles[\\/]Edition.20[0-9][0-9]\.dir[\\/]libedition_20[0-9][0-9]\.rs\.rlib +\[ 60%\] Built target Edition\.20[0-9][0-9] +\[ 80%\] Building Rust object CMakeFiles[\\/]Edition.20[0-9][0-9]\.dir[\\/]libedition_20[0-9][0-9]\.rs\.rlib +\[ 80%\] Built target Edition\.20[0-9][0-9] +\[100%\] Linking Rust executable Editions +\[100%\] Built target Editions
diff --git a/Tests/RunCMake/Rust/Editions.cmake b/Tests/RunCMake/Rust/Editions.cmake index 0520e06..95b408f 100644 --- a/Tests/RunCMake/Rust/Editions.cmake +++ b/Tests/RunCMake/Rust/Editions.cmake
@@ -1,4 +1,4 @@ -set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313") +set(CMAKE_EXPERIMENTAL_RUST "b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1") enable_language(Rust) # No Edition set, rustc defaults to 2015.
diff --git a/Tests/RunCMake/Rust/Enable.cmake b/Tests/RunCMake/Rust/Enable.cmake index ec06ab6..9bdff73 100644 --- a/Tests/RunCMake/Rust/Enable.cmake +++ b/Tests/RunCMake/Rust/Enable.cmake
@@ -1,3 +1,3 @@ -set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313") +set(CMAKE_EXPERIMENTAL_RUST "b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1") enable_language(Rust) message(STATUS "CMAKE_Rust_COMPILER='${CMAKE_Rust_COMPILER}'")
diff --git a/Tests/RunCMake/Rust/RunCMakeTest.cmake b/Tests/RunCMake/Rust/RunCMakeTest.cmake index c3d0207..ae6f602 100644 --- a/Tests/RunCMake/Rust/RunCMakeTest.cmake +++ b/Tests/RunCMake/Rust/RunCMakeTest.cmake
@@ -7,5 +7,11 @@ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Editions-build) run_cmake(Editions) set(RunCMake_TEST_NO_CLEAN 1) - run_cmake_command(Editions-build ${CMAKE_COMMAND} --build . --config Debug) + if (RunCMake_GENERATOR MATCHES "Ninja") + run_cmake_command(Editions-build-Ninja ${CMAKE_COMMAND} --build . --config Debug) + elseif(RunCMake_GENERATOR MATCHES "Makefiles") + run_cmake_command(Editions-build-UnixMakefiles ${CMAKE_COMMAND} --build . --config Debug) + else() + message(FATAL_ERROR "Unsupported ${RunCMake_GENERATOR} generator!") + endif() endblock()
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake new file mode 100644 index 0000000..1d2ee36 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake
@@ -0,0 +1,3 @@ +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) + +findAttribute(${test} "CodeSignOnCopy" TRUE 2)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake new file mode 100644 index 0000000..3ab035a --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake
@@ -0,0 +1,20 @@ +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + +add_library(MTestLib SHARED TestLib/TestLib.c TestLib/TestLib.h) +set_target_properties(MTestLib PROPERTIES + FRAMEWORK 1 + PUBLIC_HEADER TestLib/TestLib.h + ) + +add_executable(mapp1 MACOSX_BUNDLE main.m) +add_executable(mapp2 MACOSX_BUNDLE main.m) + +set_target_properties(mapp1 PROPERTIES + XCODE_EMBED_FRAMEWORKS MTestLib + XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON +) + +set_target_properties(mapp2 PROPERTIES + XCODE_EMBED_FRAMEWORKS MTestLib + XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON +)
diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake index 26749cd..70b74b8 100644 --- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
@@ -57,6 +57,19 @@ ) endblock() +block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EmbedFrameworksMultiTargets-build) + run_cmake(EmbedFrameworksMultiTargets) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(EmbedFrameworksMultiTargets-build + ${CMAKE_COMMAND} --build . + --config Debug + --target MTestLib + --target mapp1 + --target mapp2 + ) +endblock() + function(TestAppExtension platform) set(testName EmbedAppExtensions-${platform}) if(NOT platform STREQUAL "macOS")
diff --git a/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake index b1963e2..770532e 100644 --- a/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake
@@ -1,19 +1,23 @@ cmake_policy(VERSION 3.1...3.20) function(findAttribute project attr expectPresent) + set(expectCount ${ARGV3}) + + if(NOT expectPresent) + set(expectCount 0) + endif() + execute_process( - COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj - OUTPUT_VARIABLE output_var - RESULT_VARIABLE result_var + COMMAND grep -c ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj + OUTPUT_VARIABLE actualCount + OUTPUT_STRIP_TRAILING_WHITESPACE ) - if(${expectPresent}) - if(result_var) - set(RunCMake_TEST_FAILED "${attr} attribute is not set" PARENT_SCOPE) - endif() - else() - if(NOT result_var) - set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE) - endif() + if(NOT actualCount MATCHES "^[0-9]+$") + set(actualCount 0) + endif() + + if(NOT ("${expectCount}" STREQUAL "") AND NOT (actualCount EQUAL expectCount)) + set(RunCMake_TEST_FAILED "${attr} expected ${expectCount} matches, but found ${actualCount}" PARENT_SCOPE) endif() endfunction()
diff --git a/Tests/RunCMake/add_test/RunCMakeTest.cmake b/Tests/RunCMake/add_test/RunCMakeTest.cmake index 6e7d53a..69593e6 100644 --- a/Tests/RunCMake/add_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_test/RunCMakeTest.cmake
@@ -58,3 +58,50 @@ run_cmake_command(TestLauncher-test ${CMAKE_CTEST_COMMAND} -C Debug -V) endblock() unset(RunCMake_TEST_OPTIONS) + +function(run_testdependency_case CASE_NAME EXPECT_PRESENT) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestDependency-${CASE_NAME}-build) + run_cmake(TestDependency-${CASE_NAME}) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(TestDependency-${CASE_NAME}-check + ${CMAKE_COMMAND} + -DRunCMake_TEST_BINARY_DIR=${RunCMake_TEST_BINARY_DIR} + -Dexpect_present=${EXPECT_PRESENT} + -P ${RunCMake_SOURCE_DIR}/TestDependency-check-targets.cmake) + unset(RunCMake_TEST_NO_CLEAN) +endfunction() + +if(RunCMake_GENERATOR MATCHES Ninja) + block() + run_testdependency_case(DEFAULT FALSE) + run_testdependency_case(OFF FALSE) + run_cmake(TestDependency-ON-invalid-test-name) + + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestDependency-ON-build) + run_testdependency_case(ON TRUE) + + if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(TestDependency_CONFIG Debug) + else() + set(TestDependency_CONFIG "") + endif() + set(TestDependency_BUILD_CONFIG_ARG) + if(TestDependency_CONFIG) + set(TestDependency_BUILD_CONFIG_ARG --config ${TestDependency_CONFIG}) + endif() + set(RunCMake_TEST_OUTPUT_MERGE 1) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(TestDependency-ON-all + ${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG} + --target test_prep/all) + run_cmake_command(TestDependency-ON-build + ${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG} + --target test_prep/TargetBuildTest) + run_cmake_command(TestDependency-ON-build-check + ${CMAKE_COMMAND} + -DRunCMake_TEST_BINARY_DIR=${RunCMake_TEST_BINARY_DIR} + -P ${RunCMake_SOURCE_DIR}/TestDependency-build-check.cmake) + unset(RunCMake_TEST_OUTPUT_MERGE) + unset(RunCMake_TEST_NO_CLEAN) + endblock() +endif()
diff --git a/Tests/RunCMake/add_test/TestDependency-DEFAULT.cmake b/Tests/RunCMake/add_test/TestDependency-DEFAULT.cmake new file mode 100644 index 0000000..7397066 --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-DEFAULT.cmake
@@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 4.3) +include(${CMAKE_CURRENT_LIST_DIR}/TestDependency.cmake)
diff --git a/Tests/RunCMake/add_test/TestDependency-OFF.cmake b/Tests/RunCMake/add_test/TestDependency-OFF.cmake new file mode 100644 index 0000000..5ae6829 --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-OFF.cmake
@@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 4.3) +set(CMAKE_TEST_BUILD_DEPENDS OFF) +include(${CMAKE_CURRENT_LIST_DIR}/TestDependency.cmake)
diff --git a/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name-result.txt b/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name-stderr.txt b/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name-stderr.txt new file mode 100644 index 0000000..7df35de --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name-stderr.txt
@@ -0,0 +1,5 @@ +CMake Error at TestDependency-ON-invalid-test-name.cmake:[0-9]+ \(add_test\): + add_test Cannot set build dependencies for a test with NAME "Target Build + Test Invalid Name" which is not a valid target name. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name.cmake b/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name.cmake new file mode 100644 index 0000000..9264f72 --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-ON-invalid-test-name.cmake
@@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 4.3) +set(CMAKE_TEST_BUILD_DEPENDS ON) + +project(TestDependencyInvalidTestName C) + +enable_testing() + +add_custom_target(TestDependencyPrereq + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyPrereq-built.txt" + BYPRODUCTS + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyPrereq-built.txt" + VERBATIM) + +add_test(NAME "Target Build Test Invalid Name" + COMMAND + "${CMAKE_COMMAND}" -E true + BUILD_DEPENDS + TestDependencyPrereq)
diff --git a/Tests/RunCMake/add_test/TestDependency-ON.cmake b/Tests/RunCMake/add_test/TestDependency-ON.cmake new file mode 100644 index 0000000..7a4d3ab --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-ON.cmake
@@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 4.3) +set(CMAKE_TEST_BUILD_DEPENDS ON) +include(${CMAKE_CURRENT_LIST_DIR}/TestDependency.cmake)
diff --git a/Tests/RunCMake/add_test/TestDependency-build-check.cmake b/Tests/RunCMake/add_test/TestDependency-build-check.cmake new file mode 100644 index 0000000..7234dbc --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-build-check.cmake
@@ -0,0 +1,52 @@ +foreach(name IN ITEMS + TestDependencyExe + TestDependencyGenex + TestDependencyPrereq + TestDependencyFile + TestDependencySubdirPrereq + TestDependencySubdirFile) + set(candidates) + list(APPEND candidates + "${RunCMake_TEST_BINARY_DIR}/${name}-built.txt") + list(APPEND candidates + "${RunCMake_TEST_BINARY_DIR}/TestDependencySubdir/${name}-built.txt") + + set(found FALSE) + foreach(path IN LISTS candidates) + if(EXISTS "${path}") + set(found TRUE) + break() + endif() + endforeach() + + if(NOT found) + message(FATAL_ERROR + "Expected ${name}-built.txt not found.") + endif() +endforeach() + +set(prereq_file "${RunCMake_TEST_BINARY_DIR}/TestDependencyPrereq-built.txt") +if(NOT EXISTS "${prereq_file}") + message(FATAL_ERROR + "Expected TestDependencyPrereq-built.txt to be generated by DEPENDS target.") +endif() + +set(file_dep_file "${RunCMake_TEST_BINARY_DIR}/TestDependencyFile-built.txt") +if(NOT EXISTS "${file_dep_file}") + message(FATAL_ERROR + "Expected TestDependencyFile-built.txt to be generated by DEPENDS file.") +endif() + +set(subdir_prereq_file + "${RunCMake_TEST_BINARY_DIR}/TestDependencySubdir/TestDependencySubdirPrereq-built.txt") +if(NOT EXISTS "${subdir_prereq_file}") + message(FATAL_ERROR + "Expected TestDependencySubdirPrereq-built.txt to be generated by duplicate test DEPENDS target.") +endif() + +set(subdir_file_dep_file + "${RunCMake_TEST_BINARY_DIR}/TestDependencySubdir/TestDependencySubdirFile-built.txt") +if(NOT EXISTS "${subdir_file_dep_file}") + message(FATAL_ERROR + "Expected TestDependencySubdirFile-built.txt to be generated by duplicate test DEPENDS file.") +endif()
diff --git a/Tests/RunCMake/add_test/TestDependency-check-targets.cmake b/Tests/RunCMake/add_test/TestDependency-check-targets.cmake new file mode 100644 index 0000000..9185ed9 --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency-check-targets.cmake
@@ -0,0 +1,28 @@ +if(NOT DEFINED RunCMake_TEST_BINARY_DIR) + message(FATAL_ERROR "RunCMake_TEST_BINARY_DIR not set") +endif() + +if(NOT DEFINED expect_present) + message(FATAL_ERROR "expect_present not set") +endif() + +file(GLOB ninja_files LIST_DIRECTORIES false + "${RunCMake_TEST_BINARY_DIR}/*.ninja" + "${RunCMake_TEST_BINARY_DIR}/*.ninja.in") + +set(found FALSE) +foreach(ninja_file IN LISTS ninja_files) + file(READ "${ninja_file}" content) + if(content MATCHES "test_prep.all|test_prep.TargetBuildTest") + set(found TRUE) + break() + endif() +endforeach() + +if(expect_present AND NOT found) + message(FATAL_ERROR "Expected test_prep targets to be present in ninja files.") +endif() + +if(NOT expect_present AND found) + message(FATAL_ERROR "Expected test_prep targets to be absent from ninja files.") +endif()
diff --git a/Tests/RunCMake/add_test/TestDependency.cmake b/Tests/RunCMake/add_test/TestDependency.cmake new file mode 100644 index 0000000..312dd8a --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependency.cmake
@@ -0,0 +1,49 @@ +project(TestDependency C) + +enable_testing() + +add_executable(TestDependencyExe main.c) +add_custom_command(TARGET TestDependencyExe POST_BUILD + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyExe-built.txt" + BYPRODUCTS + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyExe-built.txt") + +add_executable(TestDependencyGenex main.c) +add_custom_command(TARGET TestDependencyGenex POST_BUILD + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyGenex-built.txt" + BYPRODUCTS + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyGenex-built.txt") + +add_custom_target(TestDependencyPrereq + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyPrereq-built.txt" + BYPRODUCTS + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyPrereq-built.txt" + VERBATIM) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyFile-built.txt" + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyFile-built.txt" + VERBATIM) + +add_custom_target( + FileDependsTarget + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyFile-built.txt" +) + +add_subdirectory(TestDependencySubdir) + +add_test(NAME TargetBuildTest + COMMAND + TestDependencyExe + $<TARGET_FILE:TestDependencyGenex> + BUILD_DEPENDS + TestDependencyPrereq + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencyFile-built.txt")
diff --git a/Tests/RunCMake/add_test/TestDependencySubdir/CMakeLists.txt b/Tests/RunCMake/add_test/TestDependencySubdir/CMakeLists.txt new file mode 100644 index 0000000..262230d --- /dev/null +++ b/Tests/RunCMake/add_test/TestDependencySubdir/CMakeLists.txt
@@ -0,0 +1,25 @@ +add_custom_target(TestDependencySubdirPrereq + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencySubdirPrereq-built.txt" + BYPRODUCTS + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencySubdirPrereq-built.txt" + VERBATIM) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/TestDependencySubdirFile-built.txt" + COMMAND + "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencySubdirFile-built.txt" + VERBATIM) + +add_custom_target(TestDependencySubdirFile + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/TestDependencySubdirFile-built.txt") + +# Duplicate test name with parent directory +add_test(NAME TargetBuildTest + COMMAND + "${CMAKE_COMMAND}" -E true + BUILD_DEPENDS + TestDependencySubdirPrereq + "${CMAKE_CURRENT_BINARY_DIR}/TestDependencySubdirFile-built.txt")
diff --git a/Tests/RunCMake/ctest_build/BuildPresetFromFileVar-check.cmake b/Tests/RunCMake/ctest_build/BuildPresetFromFileVar-check.cmake new file mode 100644 index 0000000..7ca59c0 --- /dev/null +++ b/Tests/RunCMake/ctest_build/BuildPresetFromFileVar-check.cmake
@@ -0,0 +1,14 @@ +file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml") +if(build_xml_file) + file(READ "${build_xml_file}" build_xml) + if(NOT build_xml MATCHES "--preset.*my-build-preset") + set(RunCMake_TEST_FAILED + "Build.xml does not contain the expected --preset argument") + endif() + if(NOT build_xml MATCHES "--presets-file") + set(RunCMake_TEST_FAILED + "Build.xml does not contain the expected --presets-file argument") + endif() +else() + set(RunCMake_TEST_FAILED "Build.xml not found") +endif()
diff --git a/Tests/RunCMake/ctest_build/BuildPresetGenericVar-check.cmake b/Tests/RunCMake/ctest_build/BuildPresetGenericVar-check.cmake new file mode 100644 index 0000000..7dd0228 --- /dev/null +++ b/Tests/RunCMake/ctest_build/BuildPresetGenericVar-check.cmake
@@ -0,0 +1,10 @@ +file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml") +if(build_xml_file) + file(READ "${build_xml_file}" build_xml) + if(NOT build_xml MATCHES "--preset.*my-build-preset") + set(RunCMake_TEST_FAILED + "Build.xml does not contain the expected --preset argument") + endif() +else() + set(RunCMake_TEST_FAILED "Build.xml not found") +endif()
diff --git a/Tests/RunCMake/ctest_build/BuildPresetVar-check.cmake b/Tests/RunCMake/ctest_build/BuildPresetVar-check.cmake new file mode 100644 index 0000000..7dd0228 --- /dev/null +++ b/Tests/RunCMake/ctest_build/BuildPresetVar-check.cmake
@@ -0,0 +1,10 @@ +file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml") +if(build_xml_file) + file(READ "${build_xml_file}" build_xml) + if(NOT build_xml MATCHES "--preset.*my-build-preset") + set(RunCMake_TEST_FAILED + "Build.xml does not contain the expected --preset argument") + endif() +else() + set(RunCMake_TEST_FAILED "Build.xml not found") +endif()
diff --git a/Tests/RunCMake/ctest_build/CMakePresets.json.in b/Tests/RunCMake/ctest_build/CMakePresets.json.in index a676de1..fca5b7e 100644 --- a/Tests/RunCMake/ctest_build/CMakePresets.json.in +++ b/Tests/RunCMake/ctest_build/CMakePresets.json.in
@@ -10,6 +10,10 @@ "name": "my-configure-preset", "generator": "@RunCMake_GENERATOR@", "binaryDir": "${sourceDir}/../BuildPreset-build" + }, + { + "name": "my-build-preset", + "inherits": "my-configure-preset" } ], "buildPresets": [
diff --git a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake index e88f901..97a1ce9 100644 --- a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
@@ -80,6 +80,26 @@ run_ctest_build(BuildPreset PRESET my-build-preset) unset(RunCMake_TEST_SOURCE_DIR) +set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/BuildPresetVar") +configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" + @ONLY) +set(CASE_TEST_PREFIX_CODE [[set(CTEST_BUILD_PRESET "my-build-preset")]]) +run_ctest(BuildPresetVar) +unset(CASE_TEST_PREFIX_CODE) +unset(RunCMake_TEST_SOURCE_DIR) + +set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/BuildPresetGenericVar") +configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" + @ONLY) +set(CASE_TEST_PREFIX_CODE [[set(CTEST_PRESET "my-build-preset")]]) +run_ctest(BuildPresetGenericVar) +unset(CASE_TEST_PREFIX_CODE) +unset(RunCMake_TEST_SOURCE_DIR) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/BuildPresetFromFile") set(custom_presets_file "${RunCMake_BINARY_DIR}/BuildPresetFromFile/custom-presets.json") @@ -93,6 +113,21 @@ unset(RunCMake_TEST_SOURCE_DIR) unset(custom_presets_file) +set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/BuildPresetFromFileVar") +set(custom_presets_file + "${RunCMake_BINARY_DIR}/BuildPresetFromFileVar/custom-presets.json") +configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${custom_presets_file}" + @ONLY) +set(CASE_TEST_PREFIX_CODE +"set(CTEST_BUILD_PRESET \"my-build-preset\") +set(CTEST_PRESETS_FILE \"${custom_presets_file}\")") +run_ctest(BuildPresetFromFileVar) +unset(CASE_TEST_PREFIX_CODE) +unset(RunCMake_TEST_SOURCE_DIR) +unset(custom_presets_file) + run_ctest_build(BuildPresetBadFile PRESET my-build-preset PRESETS_FILE /nonexistent/path/presets.json)
diff --git a/Tests/RunCMake/ctest_configure/ConfigurePresetFromFileVar-check.cmake b/Tests/RunCMake/ctest_configure/ConfigurePresetFromFileVar-check.cmake new file mode 100644 index 0000000..68c0d27 --- /dev/null +++ b/Tests/RunCMake/ctest_configure/ConfigurePresetFromFileVar-check.cmake
@@ -0,0 +1,29 @@ +if(IS_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}/build") + set(RunCMake_TEST_FAILED + "CTEST_BINARY_DIRECTORY did not override buildDir from preset") +endif() + +file(GLOB configure_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Configure.xml") +if(configure_xml_file) + file(READ "${configure_xml_file}" configure_xml) + if(NOT configure_xml MATCHES "\"--preset\" \"my-preset\"") + set(RunCMake_TEST_FAILED + "Configure.xml does not contain the expected --preset argument") + endif() + if(NOT configure_xml MATCHES "\"--presets-file\"") + set(RunCMake_TEST_FAILED + "Configure.xml does not contain the expected --presets-file argument") + endif() +else() + set(RunCMake_TEST_FAILED "Configure.xml not found") +endif() + +set(cmakecache_file "${RunCMake_TEST_BINARY_DIR}/CMakeCache.txt") +if(EXISTS "${cmakecache_file}") + file(READ "${cmakecache_file}" cmakecache_txt) + if(NOT cmakecache_txt MATCHES "MY_CUSTOM_VAR:STRING=this-gets-set") + set(RunCMake_TEST_FAILED "CMakeCache.txt does not contain MY_CUSTOM_VAR") + endif() +else() + set(RunCMake_TEST_FAILED "CMakeCache.txt not found") +endif()
diff --git a/Tests/RunCMake/ctest_configure/ConfigurePresetGenericVar-check.cmake b/Tests/RunCMake/ctest_configure/ConfigurePresetGenericVar-check.cmake new file mode 100644 index 0000000..b89b32b --- /dev/null +++ b/Tests/RunCMake/ctest_configure/ConfigurePresetGenericVar-check.cmake
@@ -0,0 +1,25 @@ +if(IS_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}/build") + set(RunCMake_TEST_FAILED + "CTEST_BINARY_DIRECTORY did not override buildDir from preset") +endif() + +file(GLOB configure_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Configure.xml") +if(configure_xml_file) + file(READ "${configure_xml_file}" configure_xml) + if(NOT configure_xml MATCHES "\"--preset\" \"my-preset\"") + set(RunCMake_TEST_FAILED + "Configure.xml does not contain the expected --preset argument") + endif() +else() + set(RunCMake_TEST_FAILED "Configure.xml not found") +endif() + +set(cmakecache_file "${RunCMake_TEST_BINARY_DIR}/CMakeCache.txt") +if(EXISTS "${cmakecache_file}") + file(READ "${cmakecache_file}" cmakecache_txt) + if(NOT cmakecache_txt MATCHES "MY_CUSTOM_VAR:STRING=this-gets-set") + set(RunCMake_TEST_FAILED "CMakeCache.txt does not contain MY_CUSTOM_VAR") + endif() +else() + set(RunCMake_TEST_FAILED "CMakeCache.txt not found") +endif()
diff --git a/Tests/RunCMake/ctest_configure/ConfigurePresetVar-check.cmake b/Tests/RunCMake/ctest_configure/ConfigurePresetVar-check.cmake new file mode 100644 index 0000000..b89b32b --- /dev/null +++ b/Tests/RunCMake/ctest_configure/ConfigurePresetVar-check.cmake
@@ -0,0 +1,25 @@ +if(IS_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}/build") + set(RunCMake_TEST_FAILED + "CTEST_BINARY_DIRECTORY did not override buildDir from preset") +endif() + +file(GLOB configure_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Configure.xml") +if(configure_xml_file) + file(READ "${configure_xml_file}" configure_xml) + if(NOT configure_xml MATCHES "\"--preset\" \"my-preset\"") + set(RunCMake_TEST_FAILED + "Configure.xml does not contain the expected --preset argument") + endif() +else() + set(RunCMake_TEST_FAILED "Configure.xml not found") +endif() + +set(cmakecache_file "${RunCMake_TEST_BINARY_DIR}/CMakeCache.txt") +if(EXISTS "${cmakecache_file}") + file(READ "${cmakecache_file}" cmakecache_txt) + if(NOT cmakecache_txt MATCHES "MY_CUSTOM_VAR:STRING=this-gets-set") + set(RunCMake_TEST_FAILED "CMakeCache.txt does not contain MY_CUSTOM_VAR") + endif() +else() + set(RunCMake_TEST_FAILED "CMakeCache.txt not found") +endif()
diff --git a/Tests/RunCMake/ctest_configure/RunCMakeTest.cmake b/Tests/RunCMake/ctest_configure/RunCMakeTest.cmake index 6b71abc..a98b64c 100644 --- a/Tests/RunCMake/ctest_configure/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_configure/RunCMakeTest.cmake
@@ -16,6 +16,24 @@ @ONLY) run_ctest_configure(ConfigurePreset PRESET my-preset) +set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/ConfigurePresetVar") +configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" + @ONLY) +set(CASE_TEST_PREFIX_CODE [[set(CTEST_CONFIGURE_PRESET "my-preset")]]) +run_ctest(ConfigurePresetVar) +unset(CASE_TEST_PREFIX_CODE) + +set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/ConfigurePresetGenericVar") +configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" + @ONLY) +set(CASE_TEST_PREFIX_CODE [[set(CTEST_PRESET "my-preset")]]) +run_ctest(ConfigurePresetGenericVar) +unset(CASE_TEST_PREFIX_CODE) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/ConfigurePresetFromFile") set(custom_presets_file "${RunCMake_BINARY_DIR}/ConfigurePresetFromFile/custom-presets.json") configure_file( @@ -24,3 +42,17 @@ @ONLY) run_ctest_configure(ConfigurePresetFromFile PRESET my-preset PRESETS_FILE "${custom_presets_file}") unset(custom_presets_file) + +set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/ConfigurePresetFromFileVar") +set(custom_presets_file "${RunCMake_BINARY_DIR}/ConfigurePresetFromFileVar/custom-presets.json") +configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${custom_presets_file}" + @ONLY) +set(CASE_TEST_PREFIX_CODE +"set(CTEST_CONFIGURE_PRESET \"my-preset\") +set(CTEST_PRESETS_FILE \"${custom_presets_file}\")") +run_ctest(ConfigurePresetFromFileVar) +unset(CASE_TEST_PREFIX_CODE) +unset(custom_presets_file) +unset(RunCMake_TEST_SOURCE_DIR)
diff --git a/Tests/RunCMake/ctest_configure/test.cmake.in b/Tests/RunCMake/ctest_configure/test.cmake.in index fa456f3..2d23360 100644 --- a/Tests/RunCMake/ctest_configure/test.cmake.in +++ b/Tests/RunCMake/ctest_configure/test.cmake.in
@@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.10) +@CASE_TEST_PREFIX_CODE@ set(CTEST_SITE "test-site") set(CTEST_BUILD_NAME "test-build-name")
diff --git a/Tests/RunCMake/ctest_test/CMakePresets.json.in b/Tests/RunCMake/ctest_test/CMakePresets.json.in index 3d0d3d0..a973948 100644 --- a/Tests/RunCMake/ctest_test/CMakePresets.json.in +++ b/Tests/RunCMake/ctest_test/CMakePresets.json.in
@@ -10,6 +10,10 @@ "name": "my-configure-preset", "generator": "@RunCMake_GENERATOR@", "binaryDir": "${sourceDir}/build" + }, + { + "name": "my-include-preset", + "inherits": "my-configure-preset" } ], "testPresets": [
diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index 3dc3f82..ea39976 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
@@ -24,6 +24,8 @@ TestPresetExclude TestPresetInclude TestPresetOverride + TestPresetVar + TestPresetGenericVar ) configure_file( "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" @@ -35,6 +37,14 @@ run_ctest_test(TestPresetInclude PRESET my-include-preset) run_ctest_test(TestPresetOverride PRESET my-include-preset INCLUDE test2) + set(CASE_TEST_PREFIX_CODE [[set(CTEST_TEST_PRESET "my-include-preset")]]) + run_ctest(TestPresetVar) + unset(CASE_TEST_PREFIX_CODE) + + set(CASE_TEST_PREFIX_CODE [[set(CTEST_PRESET "my-include-preset")]]) + run_ctest(TestPresetGenericVar) + unset(CASE_TEST_PREFIX_CODE) + set(custom_presets_file "${RunCMake_BINARY_DIR}/TestPresetFileInclude/custom-presets.json") configure_file( @@ -47,6 +57,19 @@ unset(CASE_CTEST_TEST_RAW_ARGS) unset(custom_presets_file) + set(custom_presets_file + "${RunCMake_BINARY_DIR}/TestPresetFromFileVar/custom-presets.json") + configure_file( + "${RunCMake_SOURCE_DIR}/CMakePresets.json.in" + "${custom_presets_file}" + @ONLY) + set(CASE_TEST_PREFIX_CODE +"set(CTEST_TEST_PRESET \"my-include-preset\") +set(CTEST_PRESETS_FILE \"${custom_presets_file}\")") + run_ctest(TestPresetFromFileVar) + unset(CASE_TEST_PREFIX_CODE) + unset(custom_presets_file) + set(CASE_CTEST_TEST_RAW_ARGS "PRESET my-include-preset PRESETS_FILE /nonexistent/path/presets.json") run_ctest(TestPresetBadFile)
diff --git a/Tests/RunCMake/ctest_test/TestPresetFromFileVar-stdout.txt b/Tests/RunCMake/ctest_test/TestPresetFromFileVar-stdout.txt new file mode 100644 index 0000000..a4bf544 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestPresetFromFileVar-stdout.txt
@@ -0,0 +1,4 @@ + Start [0-9]+: test1 +1/1 Test #[0-9]+: test1 \.+ Passed +[0-9\.]+ sec ++ +100% tests passed out of 1
diff --git a/Tests/RunCMake/ctest_test/TestPresetGenericVar-stderr.txt b/Tests/RunCMake/ctest_test/TestPresetGenericVar-stderr.txt new file mode 100644 index 0000000..e00bb59 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestPresetGenericVar-stderr.txt
@@ -0,0 +1 @@ +No build preset named "my-include-preset" found, ignoring CTEST_PRESET\.
diff --git a/Tests/RunCMake/ctest_test/TestPresetGenericVar-stdout.txt b/Tests/RunCMake/ctest_test/TestPresetGenericVar-stdout.txt new file mode 100644 index 0000000..a4bf544 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestPresetGenericVar-stdout.txt
@@ -0,0 +1,4 @@ + Start [0-9]+: test1 +1/1 Test #[0-9]+: test1 \.+ Passed +[0-9\.]+ sec ++ +100% tests passed out of 1
diff --git a/Tests/RunCMake/ctest_test/TestPresetVar-stdout.txt b/Tests/RunCMake/ctest_test/TestPresetVar-stdout.txt new file mode 100644 index 0000000..a4bf544 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestPresetVar-stdout.txt
@@ -0,0 +1,4 @@ + Start [0-9]+: test1 +1/1 Test #[0-9]+: test1 \.+ Passed +[0-9\.]+ sec ++ +100% tests passed out of 1
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-notfile.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-notfile.cmake index 3e4c434..80ad6ca 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-notfile.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-notfile.cmake
@@ -20,6 +20,10 @@ install(CODE [[ file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>") + + # workaround for rdar://FB22863998, an otool bug: + file(TOUCH "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>/dummy.txt") + file(GET_RUNTIME_DEPENDENCIES EXECUTABLES "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
diff --git a/Tests/RustMix/CMakeLists.txt b/Tests/RustMix/CMakeLists.txt index bf2f2c8..029f534 100644 --- a/Tests/RustMix/CMakeLists.txt +++ b/Tests/RustMix/CMakeLists.txt
@@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 4.2) -set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313") +set(CMAKE_EXPERIMENTAL_RUST "b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1") project(RustMix LANGUAGES C CXX Rust)
diff --git a/Tests/RustOnly/CMakeLists.txt b/Tests/RustOnly/CMakeLists.txt index 29b4a5b..72b6efa 100644 --- a/Tests/RustOnly/CMakeLists.txt +++ b/Tests/RustOnly/CMakeLists.txt
@@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 4.2) -set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313") +set(CMAKE_EXPERIMENTAL_RUST "b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1") project(RustOnly LANGUAGES Rust)
diff --git a/Tests/RustPie/CMakeLists.txt b/Tests/RustPie/CMakeLists.txt index 0c3b657..9adc23c 100644 --- a/Tests/RustPie/CMakeLists.txt +++ b/Tests/RustPie/CMakeLists.txt
@@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 4.2) -set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313") +set(CMAKE_EXPERIMENTAL_RUST "b6fdddce-bf66-41a5-bc5f-077f6fa4d2a1") function(setup PREFIX) add_library(${PREFIX}_static STATIC ../static.rs)
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 27049c7..e577c46 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py
@@ -896,20 +896,25 @@ app.add_transform(CMakeXRefTransform) app.add_domain(CMakeDomain) - versionlabels.update({ - 'presets-versionadded': 'Added in presets version %s', - 'presets-versionchanged': 'Changed in presets version %s', - 'presets-versionremoved': 'Removed in presets version %s', - }) - - versionlabel_classes.update({ - 'presets-versionadded': 'added', - 'presets-versionchanged': 'changed', - 'presets-versionremoved': 'removed', - }) - - app.add_directive('presets-versionadded', VersionChange) - app.add_directive('presets-versionchanged', VersionChange) - app.add_directive('presets-versionremoved', VersionChange) + version_directives = { + 'cmakefiles': 'cmakeFiles', + 'codemodel': 'codemodel', + 'presets': 'presets', + 'toolchains': 'toolchains', + } + for directive, name in version_directives.items(): + versionlabels.update({ + f'{directive}-versionadded': f'Added in {name} version %s', + f'{directive}-versionchanged': f'Changed in {name} version %s', + f'{directive}-versionremoved': f'Removed in {name} version %s', + }) + versionlabel_classes.update({ + f'{directive}-versionadded': 'added', + f'{directive}-versionchanged': 'changed', + f'{directive}-versionremoved': 'removed', + }) + app.add_directive(f'{directive}-versionadded', VersionChange) + app.add_directive(f'{directive}-versionchanged', VersionChange) + app.add_directive(f'{directive}-versionremoved', VersionChange) return {"parallel_read_safe": True}