Merge topic 'compile-commands-posix-paths'
971a8ded06 EXPORT_COMPILE_COMMANDS: Write absolute posix paths to compile_commands.json
ff119423b9 EXPORT_COMPILE_COMMANDS: Append missing newline to compile_commands.json
92fb080ed6 Tests/RunCMake/Swift: Fix CompileCommands expected regex
7d8b39226c cmGlobalNinjaGenerator: Remove obsolete TODO comment
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Ben Boeckel <ben.boeckel@kitware.com>
Merge-request: !10357
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 82d0968..c8c5bfd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -830,6 +830,46 @@
needs:
- b:linux-aarch64-package
+b:sunos-i386-package:
+ extends:
+ - .sunos_package
+ - .sunos_release_i386
+ - .cmake_build_sunos_release
+ - .cmake_release_artifacts
+ - .linux_x86_64_tags
+ - .run_only_for_package
+ needs:
+ - p:doc-package
+ variables:
+ CMAKE_CI_ARTIFACTS_NAME: "artifacts-sunos-i386"
+
+u:sunos-i386-package:
+ extends:
+ - .rsync_upload_package
+ - .run_only_for_package
+ needs:
+ - b:sunos-i386-package
+
+b:sunos-sparc-package:
+ extends:
+ - .sunos_package
+ - .sunos_release_sparc
+ - .cmake_build_sunos_release
+ - .cmake_release_artifacts
+ - .linux_x86_64_tags
+ - .run_only_for_package
+ needs:
+ - p:doc-package
+ variables:
+ CMAKE_CI_ARTIFACTS_NAME: "artifacts-sunos-sparc"
+
+u:sunos-sparc-package:
+ extends:
+ - .rsync_upload_package
+ - .run_only_for_package
+ needs:
+ - b:sunos-sparc-package
+
## Sanitizer builds
b:fedora41-asan:
diff --git a/.gitlab/artifacts.yml b/.gitlab/artifacts.yml
index 95a0a26..0750634 100644
--- a/.gitlab/artifacts.yml
+++ b/.gitlab/artifacts.yml
@@ -78,6 +78,8 @@
- ${CMAKE_CI_BUILD_DIR}/cmake-*-linux-x86_64.*
- ${CMAKE_CI_BUILD_DIR}/cmake-*-linux-aarch64.*
- ${CMAKE_CI_BUILD_DIR}/cmake-*-macos*-universal.*
+ - ${CMAKE_CI_BUILD_DIR}/cmake-*-sunos-i386.*
+ - ${CMAKE_CI_BUILD_DIR}/cmake-*-sunos-sparc.*
- ${CMAKE_CI_BUILD_DIR}/cmake-*-windows-x86_64.*
- ${CMAKE_CI_BUILD_DIR}/cmake-*-windows-i386.*
- ${CMAKE_CI_BUILD_DIR}/cmake-*-windows-arm64.*
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 461b34e..93223bb 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -30,6 +30,24 @@
variables:
BOOTSTRAP_ARGS: '-- "-DCMake_DOC_ARTIFACT_PREFIX=$CI_PROJECT_DIR/build/install-doc"'
+.sunos_release_i386:
+ image: "kitware/cmake:build-sunos-i386-deps-2025-02-14"
+
+ variables:
+ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
+ CMAKE_ARCH: i386
+
+.sunos_release_sparc:
+ image: "kitware/cmake:build-sunos-sparc-deps-2025-02-14"
+
+ variables:
+ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
+ CMAKE_ARCH: sparc
+
+.sunos_package:
+ variables:
+ CMake_DOC_ARTIFACT_PREFIX: "$CI_PROJECT_DIR/build/install-doc"
+
.needs_centos7_x86_64:
needs:
- b:centos7-x86_64
@@ -741,6 +759,33 @@
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
+.cmake_build_sunos_release:
+ stage: build
+
+ script:
+ - *before_script_linux
+ # SunOS sysroot
+ - Utilities/Release/sunos/docker/sysroot.bash $CMAKE_ARCH
+ # Initial cache
+ - mkdir -p build/
+ - cp Utilities/Release/sunos/$CMAKE_ARCH/cache.txt build/CMakeCache.txt
+ # Make sccache available.
+ - source .gitlab/ci/sccache-env.sh
+ - echo "CMAKE_C_COMPILER_LAUNCHER:STRING=sccache" >> build/CMakeCache.txt
+ - echo "CMAKE_CXX_COMPILER_LAUNCHER:STRING=sccache" >> build/CMakeCache.txt
+ # Build
+ - cd build/
+ - cmake .. -GNinja
+ -DCMAKE_DOC_DIR=doc/cmake
+ -DCMake_DOC_ARTIFACT_PREFIX="$CMake_DOC_ARTIFACT_PREFIX"
+ -DCMAKE_TOOLCHAIN_FILE="$CI_PROJECT_DIR/Utilities/Release/sunos/$CMAKE_ARCH/toolchain.cmake"
+ - ninja
+ # Package
+ - cpack -G "TGZ;STGZ"
+ - sccache --show-stats
+
+ interruptible: true
+
### Documentation
.cmake_org_help:
diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst
index 47e8e6b..333e514 100644
--- a/Help/command/cmake_minimum_required.rst
+++ b/Help/command/cmake_minimum_required.rst
@@ -8,7 +8,7 @@
cmake_minimum_required(VERSION <min>[...<policy_max>] [FATAL_ERROR])
.. versionadded:: 3.12
- The optional ``<policy_max>`` version.
+ The optional ``<policy_max>`` version behavior; ignored in older CMake.
Sets the minimum required version of cmake for a project.
Also updates the policy settings as explained below.
diff --git a/Help/command/string.rst b/Help/command/string.rst
index c510ff4..d86efc5 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -122,6 +122,12 @@
string instead of the beginning of each repeated search.
See policy :policy:`CMP0186`.
+ Zero-length matches are allowed in ``MATCHALL`` and ``REPLACE``.
+ Previously, they triggered an error.
+
+ The replacement expression may contain references to subexpressions that
+ didn't match anything. Previously, such references triggered an error.
+
.. _`Regex Specification`:
Regex Specification
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
index 5f2cb22..907b31f 100644
--- a/Help/dev/experimental.rst
+++ b/Help/dev/experimental.rst
@@ -129,7 +129,13 @@
* variable ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` to
* value ``a37d1069-1972-4901-b9c9-f194aaf2b6e0``.
-To enable instrumentation at the user-level, files should be blaced under
+To enable instrumentation at the user-level, files should be placed under
either
``<CMAKE_CONFIG_DIR>/instrumentation-a37d1069-1972-4901-b9c9-f194aaf2b6e0`` or
``<CMAKE_BINARY_DIR>/.cmake/instrumentation-a37d1069-1972-4901-b9c9-f194aaf2b6e0``.
+
+To include instrumentation data in CTest XML files (for submission to CDash),
+you need to set the following environment variables:
+
+* ``CTEST_USE_INSTRUMENTATION=1``
+* ``CTEST_EXPERIMENTAL_INSTRUMENTATION=a37d1069-1972-4901-b9c9-f194aaf2b6e0``
diff --git a/Help/envvar/CTEST_USE_INSTRUMENTATION.rst b/Help/envvar/CTEST_USE_INSTRUMENTATION.rst
new file mode 100644
index 0000000..c6c7f70
--- /dev/null
+++ b/Help/envvar/CTEST_USE_INSTRUMENTATION.rst
@@ -0,0 +1,15 @@
+CTEST_USE_INSTRUMENTATION
+-------------------------
+
+.. versionadded:: 4.0
+
+.. include:: ENV_VAR.txt
+
+.. note::
+
+ This feature is only available when experimental support for instrumentation
+ has been enabled by the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` gate.
+
+Setting this environment variable enables
+:manual:`instrumentation <cmake-instrumentation(7)>` for CTest in
+:ref:`Dashboard Client` mode.
diff --git a/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst b/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst
new file mode 100644
index 0000000..d7f7477
--- /dev/null
+++ b/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst
@@ -0,0 +1,17 @@
+CTEST_USE_VERBOSE_INSTRUMENTATION
+---------------------------------
+
+.. versionadded:: 4.0
+
+.. include:: ENV_VAR.txt
+
+.. note::
+
+ This feature is only available when experimental support for instrumentation
+ has been enabled by the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` gate.
+
+Setting this environment variable causes CTest to report the full
+command line (including arguments) to CDash for each instrumented command.
+By default, CTest truncates the command line at the first space.
+
+See also :envvar:`CTEST_USE_INSTRUMENTATION`
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index fe3e703..140fc83 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -116,7 +116,9 @@
/envvar/CTEST_OUTPUT_ON_FAILURE
/envvar/CTEST_PARALLEL_LEVEL
/envvar/CTEST_PROGRESS_OUTPUT
+ /envvar/CTEST_USE_INSTRUMENTATION
/envvar/CTEST_USE_LAUNCHERS_DEFAULT
+ /envvar/CTEST_USE_VERBOSE_INSTRUMENTATION
/envvar/DASHBOARD_TEST_FROM_CTEST
Environment Variables for the CMake curses interface
diff --git a/Help/manual/cmake-instrumentation.7.rst b/Help/manual/cmake-instrumentation.7.rst
index 7b2d1e6..d36bf62 100644
--- a/Help/manual/cmake-instrumentation.7.rst
+++ b/Help/manual/cmake-instrumentation.7.rst
@@ -53,7 +53,7 @@
than the previous indexing.
Indexing and can also be performed by manually invoking
-``ctest --collect-instrumentation``.
+``ctest --collect-instrumentation <build>``.
Callbacks
---------
@@ -94,6 +94,37 @@
the :envvar:`CMAKE_CONFIG_DIR` under
``<config_dir>/instrumentation/<version>/query/``.
+Enabling Instrumentation for CDash Submissions
+----------------------------------------------
+
+You can enable instrumentation when using CTest in :ref:`Dashboard Client`
+mode by setting the :envvar:`CTEST_USE_INSTRUMENTATION` environment variable
+to the current UUID for the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` feature.
+Doing so automatically enables the ``dynamicSystemInformation`` query.
+
+The following table shows how each type of instrumented command gets mapped
+to a corresponding type of CTest XML file.
+
+=================================================== ==================
+:ref:`Snippet Role <cmake-instrumentation Data v1>` CTest XML File
+=================================================== ==================
+``configure`` ``Configure.xml``
+``generate`` ``Configure.xml``
+``compile`` ``Build.xml``
+``link`` ``Build.xml``
+``custom`` ``Build.xml``
+``build`` unused!
+``cmakeBuild`` ``Build.xml``
+``cmakeInstall`` ``Build.xml``
+``install`` ``Build.xml``
+``ctest`` ``Build.xml``
+``test`` ``Test.xml``
+=================================================== ==================
+
+By default the command line reported to CDash is truncated at the first space.
+You can instead choose to report the full command line (including arguments)
+by setting :envvar:`CTEST_USE_VERBOSE_INSTRUMENTATION` to 1.
+
.. _`cmake-instrumentation API v1`:
API v1
@@ -123,6 +154,10 @@
files, they should never be removed by other processes. Data collected here
remains until after `Indexing`_ occurs and all `Callbacks`_ are executed.
+``cdash/``
+ Holds temporary files used internally to generate XML content to be submitted
+ to CDash.
+
.. _`cmake-instrumentation v1 Query Files`:
v1 Query Files
@@ -270,7 +305,7 @@
``target``
The CMake target associated with the command. Only included when ``role`` is
- one of ``compile``, ``link``, ``custom``.
+ ``compile`` or ``link``.
``targetType``
The :prop_tgt:`TYPE` of the target. Only included when ``role`` is
@@ -375,7 +410,7 @@
The name of the hook responsible for generating the index file. In addition
to the hooks that can be specified by one of the `v1 Query Files`_, this value may
be set to ``manual`` if indexing is performed by invoking
- ``ctest --collect-instrumentation``.
+ ``ctest --collect-instrumentation <build>``.
``snippets``
Contains a list of `v1 Snippet File`_. This includes all snippet files
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 9f3de09..7c46a2a 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -98,6 +98,8 @@
.. toctree::
:maxdepth: 1
+ CMP0188: The FindGCCXML module is removed. </policy/CMP0188>
+ CMP0187: Include source file without an extension after the same name with an extension. </policy/CMP0187>
CMP0186: Regular expressions match ^ at most once in repeated searches. </policy/CMP0186>
Policies Introduced by CMake 4.0
diff --git a/Help/policy/CMP0187.rst b/Help/policy/CMP0187.rst
new file mode 100644
index 0000000..d833d84
--- /dev/null
+++ b/Help/policy/CMP0187.rst
@@ -0,0 +1,33 @@
+CMP0187
+-------
+
+.. versionadded:: 4.1
+
+Include source file without an extension after the same name with an extension.
+
+In CMake 4.0 and below, if two source files have the same filename and only one
+file has a file extension and the file with the extension is listed first, the
+file without the extension is omitted from the target.
+
+For example, the following library target only include ``hello.c`` in the
+target, but omits the file ``hello``.
+
+.. code-block:: cmake
+
+ add_library(library hello.c hello)
+
+If the file without the extension is listed before the file with the extension,
+both files are included in the target.
+
+Starting in CMake 4.1, CMake includes both files in the library target.
+
+This policy has no effect if :policy:`CMP0115` uses the ``OLD`` behavior.
+
+The ``OLD`` behavior for this policy is to omit the file without the extension.
+The ``NEW`` behavior for this policy is to include it.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.1
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0188.rst b/Help/policy/CMP0188.rst
new file mode 100644
index 0000000..6b4cb83
--- /dev/null
+++ b/Help/policy/CMP0188.rst
@@ -0,0 +1,21 @@
+CMP0188
+-------
+
+.. versionadded:: 4.1
+
+The :module:`FindGCCXML` module is removed.
+
+CMake 4.0 and below provide the :module:`FindGCCXML` module, but the GCC-XML
+tool has long been superseded by CastXML. CMake 4.1 and above prefer to not
+provide the :module:`FindGCCXML` module. This policy provides compatibility
+for projects that have not been ported away from it.
+
+The ``OLD`` behavior of this policy is for ``find_package(GCCXML)`` to load
+the deprecated module. The ``NEW`` behavior is for ``find_package(GCCXML)``
+to fail as if the module does not exist.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.1
+.. |WARNS_OR_DOES_NOT_WARN| replace:: warns
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/4.0.rst b/Help/release/4.0.rst
index b1102d5..a7a7860 100644
--- a/Help/release/4.0.rst
+++ b/Help/release/4.0.rst
@@ -73,7 +73,7 @@
See policy :policy:`CMP0184`.
* The :variable:`CMAKE_POLICY_VERSION_MINIMUM` variable was added to
- help pacakgers and end users try to configure existing projects that
+ help packagers and end users try to configure existing projects that
have not been updated to work with supported CMake versions.
* The :variable:`CMAKE_XCODE_SCHEME_LLDB_INIT_FILE` variable and corresponding
@@ -236,3 +236,8 @@
now only shown when the message log level is set to ``VERBOSE``, ``DEBUG``,
or ``TRACE`` via the :option:`cmake --log-level` option or the
:variable:`CMAKE_MESSAGE_LOG_LEVEL` cache variable.
+
+* Precompiled SunOS ``sparc`` and ``i386`` binaries are now provided
+ on `cmake.org`_.
+
+.. _`cmake.org`: https://cmake.org/download/
diff --git a/Help/release/dev/regex-fixes.rst b/Help/release/dev/regex-fixes.rst
index e979c03..82d1fad 100644
--- a/Help/release/dev/regex-fixes.rst
+++ b/Help/release/dev/regex-fixes.rst
@@ -3,3 +3,8 @@
* Regular expressions match the ``^`` anchor at most once in repeated
searches, at the start of the input. See policy :policy:`CMP0186`.
+
+* References to unmatched groups are allowed, they are replaced with empty
+ strings.
+
+* Zero-length matches are always allowed.
diff --git a/Help/release/dev/remove-FindGCCXML.rst b/Help/release/dev/remove-FindGCCXML.rst
new file mode 100644
index 0000000..7f17b91
--- /dev/null
+++ b/Help/release/dev/remove-FindGCCXML.rst
@@ -0,0 +1,5 @@
+remove-FindGCCXML
+-----------------
+
+* The :module:`FindGCCXML` module has been deprecated via policy
+ :policy:`CMP0188`. Port projects to CastXML instead.
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index c0877cc..cf9a055 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -1203,7 +1203,7 @@
# when CUDA language is disabled
if(NOT TARGET CUDA::cudart_static_deps)
add_library(CUDA::cudart_static_deps IMPORTED INTERFACE)
- if(UNIX AND (CMAKE_C_COMPILER OR CMAKE_CXX_COMPILER))
+ if(UNIX AND (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED))
find_package(Threads REQUIRED)
target_link_libraries(CUDA::cudart_static_deps INTERFACE Threads::Threads ${CMAKE_DL_LIBS})
endif()
diff --git a/Modules/FindGCCXML.cmake b/Modules/FindGCCXML.cmake
index e6c7f24..4da19fe 100644
--- a/Modules/FindGCCXML.cmake
+++ b/Modules/FindGCCXML.cmake
@@ -5,17 +5,28 @@
FindGCCXML
----------
+.. versionchanged:: 4.1
+ This module is available only if policy :policy:`CMP0188` is not set to ``NEW``.
+ Port projects to search for CastXML by calling ``find_program`` directly.
+
Find the GCC-XML front-end executable.
-
-
This module will define the following variables:
-::
-
- GCCXML - the GCC-XML front-end executable.
+``GCCXML``
+ The GCC-XML front-end executable.
#]=======================================================================]
+cmake_policy(GET CMP0188 _FindGCCXML_CMP0188)
+if(_FindGCCXML_CMP0188 STREQUAL "NEW")
+ message(FATAL_ERROR "The FindGCCXML module has been removed by policy CMP0188.")
+endif()
+
+if(_FindGCCXML_testing)
+ set(_FindGCCXML_included TRUE)
+ return()
+endif()
+
find_program(GCCXML
NAMES gccxml
../GCC_XML/gccxml
diff --git a/Modules/FindGettext.cmake b/Modules/FindGettext.cmake
index b982bb9..c38f9f5 100644
--- a/Modules/FindGettext.cmake
+++ b/Modules/FindGettext.cmake
@@ -52,7 +52,7 @@
[INSTALL_DESTINATION <destdir>]
LANGUAGES <lang>...)
- This function creates a custom target "potfile" which processes the given
+ This function creates a custom target "potfiles" which processes the given
.pot file to .mo files. Options:
``ALL``
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index e66a42f..e8039aa 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -536,7 +536,7 @@
# It has to be called as "compchk.sh <arch> <compiler>". Here, <arch> is one out of 32 (i686), 64 (ia64) or 32e (x86_64).
# The compiler is identified by filename, and can be either the MPI compiler or the underlying compiler.
# NOTE: It is vital to run this script while the environment variables are set up, otherwise it can check the wrong compiler.
- if(MPI_COMPILE_CMDLINE MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)")
+ if(MPI_COMPILE_CMDLINE MATCHES "^([^\"\n ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)")
# Now CMAKE_MATCH_1 contains the path to the compchk.sh file and CMAKE_MATCH_2 the architecture flag.
unset(COMPILER_CHECKER_OUTPUT)
execute_process(
@@ -551,7 +551,7 @@
endif()
else()
# Since the check passed, we can remove the compchk.sh script.
- string(REGEX REPLACE "^([^\" ]+|\"[^\"]+\")/compchk.sh.*\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}")
+ string(REGEX REPLACE "^([^\"\n ]+|\"[^\"]+\")/compchk.sh.*\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}")
endif()
endif()
endif()
@@ -624,10 +624,10 @@
# Especially with M(VA)PICH-1, this appears to happen erroneously, and therefore we should translate
# this output into an additional include directory and then drop it from the output.
# noqa: spellcheck on
- if(MPI_COMPILE_CMDLINE MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h")
+ if(MPI_COMPILE_CMDLINE MATCHES "^ln -s ([^\"\n ]+|\"[^\"]+\") mpif.h")
get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY)
- string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}")
- string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}")
+ string(REGEX REPLACE "^ln -s ([^\"\n ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}")
+ string(REGEX REPLACE "^ln -s ([^\"\n ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}")
string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}")
string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}")
endif()
@@ -645,7 +645,7 @@
# on Windows seems to require any specific ones, either.
if(NOT MSVC)
# Extract compile options from the compile command line.
- string(REGEX MATCHALL "(^| )-f([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}")
+ string(REGEX MATCHALL "(^| )-f([^\"\n ]+|\"[^\"]+\")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}")
foreach(_MPI_COMPILE_OPTION IN LISTS MPI_ALL_COMPILE_OPTIONS)
string(REGEX REPLACE "^ " "" _MPI_COMPILE_OPTION "${_MPI_COMPILE_OPTION}")
@@ -673,7 +673,7 @@
endif()
# Same deal as above, for the definitions.
- string(REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}-D *([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}")
+ string(REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}-D *([^\"\n ]+|\"[^\"]+\")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}")
foreach(_MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS)
string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}-D *" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}")
@@ -684,7 +684,7 @@
endforeach()
# Extract include paths from compile command line
- string(REGEX MATCHALL "(^|\n| )${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *([^\" ]+|\"[^\"]+\")"
+ string(REGEX MATCHALL "(^|\n| )${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *([^\"\n ]+|\"[^\"]+\")"
MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}")
# If extracting failed to work, we'll try using -showme:incdirs.
@@ -707,7 +707,7 @@
endforeach()
# The next step are linker flags and library directories. Here, we first take the flags given in raw -L or -LIBPATH: syntax.
- string(REGEX MATCHALL "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\"[^\"]+\")" MPI_DIRECT_LINK_PATHS "${MPI_LINK_CMDLINE}")
+ string(REGEX MATCHALL "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\"\n ]+|\"[^\"]+\")" MPI_DIRECT_LINK_PATHS "${MPI_LINK_CMDLINE}")
foreach(_MPI_LPATH IN LISTS MPI_DIRECT_LINK_PATHS)
string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *" "" _MPI_LPATH "${_MPI_LPATH}")
list(APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}")
@@ -715,7 +715,7 @@
# If the link commandline hasn't been filtered (e.g. when using MSVC and /link), we need to extract the relevant parts first.
if(NOT _MPI_FILTERED_LINK_INFORMATION)
- string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\"[^\"]+\")" MPI_LINK_FLAGS "${MPI_LINK_CMDLINE}")
+ string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\"\n ]+|\"[^\"]+\")" MPI_LINK_FLAGS "${MPI_LINK_CMDLINE}")
# In this case, we could also find some indirectly given linker paths, e.g. prefixed by -Xlinker or -Wl,
# Since syntaxes like -Wl,-L -Wl,/my/path/to/lib are also valid, we parse these paths by first removing -Wl, and -Xlinker
@@ -724,7 +724,7 @@
# Now we can parse the leftover output. Note that spaces can now be handled since the above example would reduce to
# -L /my/path/to/lib and can be extracted correctly.
- string(REGEX MATCHALL "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)([^\" ]+|\"[^\"]+\")"
+ string(REGEX MATCHALL "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)([^\"\n ]+|\"[^\"]+\")"
MPI_INDIRECT_LINK_PATHS "${MPI_LINK_FLAGS_RAW}")
foreach(_MPI_LPATH IN LISTS MPI_INDIRECT_LINK_PATHS)
@@ -733,7 +733,7 @@
endforeach()
# We need to remove the flags we extracted from the linker flag list now.
- string(REGEX REPLACE "(^| )(-Wl,|-Xlinker +)(${CMAKE_LIBRARY_PATH_FLAG},? *(-Wl,|-Xlinker +)?|--library-path=)([^\" ]+|\"[^\"]+\")" ""
+ string(REGEX REPLACE "(^| )(-Wl,|-Xlinker +)(${CMAKE_LIBRARY_PATH_FLAG},? *(-Wl,|-Xlinker +)?|--library-path=)([^\"\n ]+|\"[^\"]+\")" ""
MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}")
# Some MPI implementations pass on options they themselves were built with. Since -z,noexecstack is a common
@@ -742,7 +742,7 @@
string(REGEX REPLACE "(^| )-Xlinker +-z +-Xlinker +[^ ]+" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}")
# We only consider options of the form -Wl or -Xlinker:
- string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE_FILTERED}")
+ string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\"\n ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE_FILTERED}")
# As a next step, we assemble the linker flags extracted in a preliminary flags string
foreach(_MPI_LINK_FLAG IN LISTS MPI_ALL_LINK_FLAGS)
@@ -755,7 +755,7 @@
endforeach()
else()
# In the filtered case, we obtain the link time flags by just stripping the library paths.
- string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\"[^\"]+\")" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}")
+ string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\"\n ]+|\"[^\"]+\")" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}")
endif()
# If we failed to extract any linker paths, we'll try using the -showme:libdirs option with the MPI compiler.
@@ -777,7 +777,7 @@
# Extract the set of libraries to link against from the link command line
# This only makes sense if CMAKE_LINK_LIBRARY_FLAG is defined, i.e. a -lxxxx syntax is supported by the compiler.
if(CMAKE_LINK_LIBRARY_FLAG)
- string(REGEX MATCHALL "(^| )${CMAKE_LINK_LIBRARY_FLAG}([^\" ]+|\"[^\"]+\")"
+ string(REGEX MATCHALL "(^| )${CMAKE_LINK_LIBRARY_FLAG}([^\"\n ]+|\"[^\"]+\")"
MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES)
@@ -800,7 +800,7 @@
else()
string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_SHARED_LIBRARY_SUFFIX}")
endif()
- set(_MPI_LIB_NAME_REGEX "(([^\" ]+(${_MPI_LIB_SUFFIX_REGEX}))|(\"[^\"]+(${_MPI_LIB_SUFFIX_REGEX})\"))( +|$)")
+ set(_MPI_LIB_NAME_REGEX "(([^\"\n ]+(${_MPI_LIB_SUFFIX_REGEX}))|(\"[^\"]+(${_MPI_LIB_SUFFIX_REGEX})\"))( +|$)")
string(REPLACE "." "\\." _MPI_LIB_NAME_REGEX "${_MPI_LIB_NAME_REGEX}")
string(REGEX MATCHALL "${_MPI_LIB_NAME_REGEX}" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 080e99f..c12e07a 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 0)
-set(CMake_VERSION_PATCH 20250215)
+set(CMake_VERSION_PATCH 20250220)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
@@ -24,14 +24,15 @@
set(git_info [==[$Format:%h %s$]==])
# Otherwise, try to identify the current development source version.
+ get_filename_component(git_toplevel "${CMAKE_CURRENT_LIST_DIR}" PATH)
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
- AND EXISTS ${CMake_SOURCE_DIR}/.git)
+ AND EXISTS "${git_toplevel}/.git")
find_package(Git QUIET)
if(GIT_FOUND)
macro(_git)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${ARGN}
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
+ WORKING_DIRECTORY "${git_toplevel}"
RESULT_VARIABLE _git_res
OUTPUT_VARIABLE _git_out OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _git_err ERROR_STRIP_TRAILING_WHITESPACE
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index af54e56..9cc1110 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -11,6 +11,7 @@
#include <cm/string_view>
#include <cmext/algorithm>
+#include <cm3p/json/value.h>
#include <cm3p/uv.h>
#include "cmsys/Directory.hxx"
@@ -21,6 +22,9 @@
#include "cmDuration.h"
#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
+#include "cmInstrumentation.h"
+#include "cmInstrumentationQuery.h"
+#include "cmJSONState.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
@@ -429,6 +433,11 @@
} else {
this->GenerateXMLLogScraped(xml);
}
+
+ this->CTest->GetInstrumentation().CollectTimingData(
+ cmInstrumentationQuery::Hook::PrepareForCDash);
+ this->GenerateInstrumentationXML(xml);
+
this->GenerateXMLFooter(xml, elapsed_build_time);
if (!res || retVal || this->TotalErrors > 0) {
@@ -595,6 +604,88 @@
}
}
+void cmCTestBuildHandler::GenerateInstrumentationXML(cmXMLWriter& xml)
+{
+ // Record instrumentation data on a per-target basis.
+ cmsys::Directory targets_dir;
+ std::string targets_snippet_dir = cmStrCat(
+ this->CTest->GetInstrumentation().GetCDashDir(), "/build/targets");
+ if (targets_dir.Load(targets_snippet_dir) &&
+ targets_dir.GetNumberOfFiles() > 0) {
+ xml.StartElement("Targets");
+ for (unsigned int i = 0; i < targets_dir.GetNumberOfFiles(); i++) {
+ if (!targets_dir.FileIsDirectory(i)) {
+ continue;
+ }
+ std::string target_name = targets_dir.GetFile(i);
+ if (target_name == "." || target_name == "..") {
+ continue;
+ }
+ std::string target_type = "UNKNOWN";
+
+ xml.StartElement("Target");
+ xml.Attribute("name", target_name);
+
+ // Check if we have a link snippet for this target.
+ cmsys::Directory target_dir;
+ if (!target_dir.Load(targets_dir.GetFilePath(i))) {
+ cmSystemTools::Error(
+ cmStrCat("Error loading directory ", targets_dir.GetFilePath(i)));
+ }
+ Json::Value link_item;
+ for (unsigned int j = 0; j < target_dir.GetNumberOfFiles(); j++) {
+ std::string fname = target_dir.GetFile(j);
+ if (fname.rfind("link-", 0) == 0) {
+ std::string fpath = target_dir.GetFilePath(j);
+ cmJSONState parseState = cmJSONState(fpath, &link_item);
+ if (!parseState.errors.empty()) {
+ cmSystemTools::Error(parseState.GetErrorMessage(true));
+ break;
+ }
+
+ if (!link_item.isObject()) {
+ std::string error_msg =
+ cmStrCat("Expected snippet ", fpath, " to contain an object");
+ cmSystemTools::Error(error_msg);
+ break;
+ }
+ break;
+ }
+ }
+
+ // If so, parse targetType and targetLabels (optional) from it.
+ if (link_item.isMember("targetType")) {
+ target_type = link_item["targetType"].asString();
+ }
+
+ xml.Attribute("type", target_type);
+
+ if (link_item.isMember("targetLabels") &&
+ !link_item["targetLabels"].empty()) {
+ xml.StartElement("Labels");
+ for (auto const& json_label_item : link_item["targetLabels"]) {
+ xml.Element("Label", json_label_item.asString());
+ }
+ xml.EndElement(); // Labels
+ }
+
+ // Write instrumendation data for this target.
+ std::string target_subdir = cmStrCat("build/targets/", target_name);
+ this->CTest->ConvertInstrumentationSnippetsToXML(xml, target_subdir);
+ std::string target_dir_fullpath = cmStrCat(
+ this->CTest->GetInstrumentation().GetCDashDir(), '/', target_subdir);
+ if (cmSystemTools::FileIsDirectory(target_dir_fullpath)) {
+ cmSystemTools::RemoveADirectory(target_dir_fullpath);
+ }
+ xml.EndElement(); // Target
+ }
+ xml.EndElement(); // Targets
+ }
+
+ // Also record instrumentation data for custom commands (no target).
+ this->CTest->ConvertInstrumentationSnippetsToXML(xml, "build/commands");
+}
+
void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
cmDuration elapsed_build_time)
{
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 9d9b847..a455346 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -85,6 +85,7 @@
void GenerateXMLHeader(cmXMLWriter& xml);
void GenerateXMLLaunched(cmXMLWriter& xml);
void GenerateXMLLogScraped(cmXMLWriter& xml);
+ void GenerateInstrumentationXML(cmXMLWriter& xml);
void GenerateXMLFooter(cmXMLWriter& xml, cmDuration elapsed_build_time);
bool IsLaunchedErrorFile(char const* fname);
bool IsLaunchedWarningFile(char const* fname);
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 820eeae..4657bbd 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -17,6 +17,8 @@
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
+#include "cmInstrumentation.h"
+#include "cmInstrumentationQuery.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
@@ -203,6 +205,11 @@
xml.Element("EndDateTime", endDateTime);
xml.Element("EndConfigureTime", endTime);
xml.Element("ElapsedMinutes", elapsedMinutes.count());
+
+ this->CTest->GetInstrumentation().CollectTimingData(
+ cmInstrumentationQuery::Hook::PrepareForCDash);
+ this->CTest->ConvertInstrumentationSnippetsToXML(xml, "configure");
+
xml.EndElement(); // Configure
this->CTest->EndXML(xml);
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 2f25de7..200bd7d 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -268,7 +268,9 @@
{
auto instrumentation = cmInstrumentation(this->Reporter.OptionBuildDir);
std::map<std::string, std::string> options;
- options["target"] = this->Reporter.OptionTargetName;
+ if (this->Reporter.OptionTargetName != "TARGET_NAME") {
+ options["target"] = this->Reporter.OptionTargetName;
+ }
options["source"] = this->Reporter.OptionSource;
options["language"] = this->Reporter.OptionLanguage;
options["targetType"] = this->Reporter.OptionTargetType;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 42dc0af..4076347 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -21,6 +21,7 @@
#include "cmCTestMemCheckHandler.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmDuration.h"
+#include "cmInstrumentation.h"
#include "cmProcess.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -34,7 +35,6 @@
, CTest(MultiTestHandler.CTest)
, TestHandler(MultiTestHandler.TestHandler)
, TestProperties(MultiTestHandler.Properties[Index])
- , Instrumentation(cmSystemTools::GetLogicalWorkingDirectory())
{
}
@@ -664,8 +664,8 @@
return false;
}
this->StartTime = this->CTest->CurrentTime();
- if (this->Instrumentation.HasQuery()) {
- this->Instrumentation.GetPreTestStats();
+ if (this->CTest->GetInstrumentation().HasQuery()) {
+ this->CTest->GetInstrumentation().GetPreTestStats();
}
return this->ForkProcess();
@@ -1016,12 +1016,13 @@
void cmCTestRunTest::FinalizeTest(bool started)
{
- if (this->Instrumentation.HasQuery()) {
- this->Instrumentation.InstrumentTest(
+ if (this->CTest->GetInstrumentation().HasQuery()) {
+ std::string data_file = this->CTest->GetInstrumentation().InstrumentTest(
this->TestProperties->Name, this->ActualCommand, this->Arguments,
this->TestProcess->GetExitValue(), this->TestProcess->GetStartTime(),
this->TestProcess->GetSystemStartTime(),
this->GetCTest()->GetConfigType());
+ this->TestResult.InstrumentationFile = data_file;
}
this->MultiTestHandler.FinishTestProcess(this->TestProcess->GetRunner(),
started);
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index fd5e037..05a5f76 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -14,7 +14,6 @@
#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestTestHandler.h"
-#include "cmInstrumentation.h"
#include "cmProcess.h"
/** \class cmRunTest
@@ -141,7 +140,6 @@
int NumberOfRunsTotal = 1; // default to 1 run of the test
bool RunAgain = false; // default to not having to run again
size_t TotalNumberOfTests;
- cmInstrumentation Instrumentation;
};
inline int getNumWidth(size_t n)
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index afe505d..1f45b9d 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -41,6 +41,8 @@
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
+#include "cmInstrumentation.h"
+#include "cmInstrumentationQuery.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmState.h"
@@ -1381,6 +1383,9 @@
return;
}
+ this->CTest->GetInstrumentation().CollectTimingData(
+ cmInstrumentationQuery::Hook::PrepareForCDash);
+
this->CTest->StartXML(xml, this->CMake, this->AppendXML);
this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("Testing");
@@ -1395,7 +1400,6 @@
for (cmCTestTestResult& result : this->TestResults) {
this->WriteTestResultHeader(xml, result);
xml.StartElement("Results");
-
if (result.Status != cmCTestTestHandler::NOT_RUN) {
if (result.Status != cmCTestTestHandler::COMPLETED ||
result.ReturnValue) {
@@ -1473,6 +1477,15 @@
xml.Content(result.Output);
xml.EndElement(); // Value
xml.EndElement(); // Measurement
+
+ if (!result.InstrumentationFile.empty()) {
+ std::string instrument_file_path =
+ cmStrCat(this->CTest->GetInstrumentation().GetCDashDir(), "/test/",
+ result.InstrumentationFile);
+ this->CTest->ConvertInstrumentationJSONFileToXML(instrument_file_path,
+ xml);
+ }
+
xml.EndElement(); // Results
this->AttachFiles(xml, result);
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 393b3d3..b97d6b7 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -192,6 +192,7 @@
std::string CustomCompletionStatus;
std::string Output;
std::string TestMeasurementsOutput;
+ std::string InstrumentationFile;
int TestCount = 0;
cmCTestTestProperties* Properties = nullptr;
};
@@ -250,6 +251,7 @@
cmCTestTestResult const& result);
void WriteTestResultFooter(cmXMLWriter& xml,
cmCTestTestResult const& result);
+
// Write attached test files into the xml
void AttachFiles(cmXMLWriter& xml, cmCTestTestResult& result);
void AttachFile(cmXMLWriter& xml, std::string const& file,
diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx
index b11fd79..1a79caa 100644
--- a/Source/cmBase32.cxx
+++ b/Source/cmBase32.cxx
@@ -55,15 +55,15 @@
size_t remain = static_cast<size_t>(end - input);
if (remain != 0) {
// Temporary source buffer filled up with 0s
- unsigned char extended[blockSize];
+ unsigned char padded[blockSize];
for (size_t ii = 0; ii != remain; ++ii) {
- extended[ii] = input[ii];
+ padded[ii] = input[ii];
}
for (size_t ii = remain; ii != blockSize; ++ii) {
- extended[ii] = 0;
+ padded[ii] = 0;
}
- Base32Encode5(extended, buffer);
+ Base32Encode5(padded, buffer);
size_t numPad(0);
switch (remain) {
case 1:
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 0bb9260..2e0b07e 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -10,7 +10,6 @@
#include <cstdlib>
#include <cstring>
#include <ctime>
-#include <functional>
#include <initializer_list>
#include <iostream>
#include <map>
@@ -27,6 +26,7 @@
#include <cmext/string_view>
#include <cm3p/curl/curl.h>
+#include <cm3p/json/value.h>
#include <cm3p/uv.h>
#include <cm3p/zlib.h>
@@ -115,6 +115,8 @@
bool UseHTTP10 = false;
bool PrintLabels = false;
bool Failover = false;
+ bool UseVerboseInstrumentation = false;
+ cmJSONState parseState;
bool FlushTestProgressLine = false;
@@ -195,6 +197,8 @@
cmCTestTestOptions TestOptions;
std::vector<std::string> CommandLineHttpHeaders;
+
+ std::unique_ptr<cmInstrumentation> Instrumentation;
};
struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
@@ -320,6 +324,11 @@
if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) {
this->Impl->TestProgressOutput = !cmIsOff(envValue);
}
+ envValue.clear();
+ if (cmSystemTools::GetEnv("CTEST_USE_VERBOSE_INSTRUMENTATION", envValue)) {
+ this->Impl->UseVerboseInstrumentation = !cmIsOff(envValue);
+ }
+ envValue.clear();
this->Impl->Parts[PartStart].SetName("Start");
this->Impl->Parts[PartUpdate].SetName("Update");
@@ -2628,32 +2637,23 @@
}
#endif
- cmInstrumentation instrumentation(
- cmSystemTools::GetCurrentWorkingDirectory());
- std::function<int()> doTest = [this, &cmakeAndTest, &runScripts,
- &processSteps]() -> int {
- // now what should cmake do? if --build-and-test was specified then
- // we run the build and test handler and return
- if (cmakeAndTest) {
- return this->RunCMakeAndTest();
- }
+ // now what should cmake do? if --build-and-test was specified then
+ // we run the build and test handler and return
+ if (cmakeAndTest) {
+ return this->RunCMakeAndTest();
+ }
- // -S, -SP, and/or -SP was specified
- if (!runScripts.empty()) {
- return this->RunScripts(runScripts);
- }
+ // -S, -SP, and/or -SP was specified
+ if (!runScripts.empty()) {
+ return this->RunScripts(runScripts);
+ }
- // -D, -T, and/or -M was specified
- if (processSteps) {
- return this->ProcessSteps();
- }
+ // -D, -T, and/or -M was specified
+ if (processSteps) {
+ return this->ProcessSteps();
+ }
- return this->ExecuteTests();
- };
- int ret = instrumentation.InstrumentCommand("ctest", args,
- [doTest]() { return doTest(); });
- instrumentation.CollectTimingData(cmInstrumentationQuery::Hook::PostTest);
- return ret;
+ return this->ExecuteTests(args);
}
int cmCTest::RunScripts(
@@ -2677,7 +2677,7 @@
return res;
}
-int cmCTest::ExecuteTests()
+int cmCTest::ExecuteTests(std::vector<std::string> const& args)
{
this->Impl->ExtraVerbose = this->Impl->Verbose;
this->Impl->Verbose = true;
@@ -2722,7 +2722,14 @@
}
handler.SetVerbose(this->Impl->Verbose);
- if (handler.ProcessHandler() < 0) {
+
+ cmInstrumentation instrumentation(this->GetBinaryDir());
+ auto processHandler = [&handler]() -> int {
+ return handler.ProcessHandler();
+ };
+ int ret = instrumentation.InstrumentCommand("ctest", args, processHandler);
+ instrumentation.CollectTimingData(cmInstrumentationQuery::Hook::PostTest);
+ if (ret < 0) {
cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest\n");
if (!this->Impl->OutputTestOutputOnTestFailure) {
std::string const lastTestLog =
@@ -3673,3 +3680,128 @@
}
return true;
}
+
+cmInstrumentation& cmCTest::GetInstrumentation()
+{
+ if (!this->Impl->Instrumentation) {
+ this->Impl->Instrumentation =
+ cm::make_unique<cmInstrumentation>(this->GetBinaryDir());
+ }
+ return *this->Impl->Instrumentation;
+}
+
+bool cmCTest::GetUseVerboseInstrumentation() const
+{
+ return this->Impl->UseVerboseInstrumentation;
+}
+
+void cmCTest::ConvertInstrumentationSnippetsToXML(cmXMLWriter& xml,
+ std::string const& subdir)
+{
+ std::string data_dir =
+ cmStrCat(this->GetInstrumentation().GetCDashDir(), '/', subdir);
+
+ cmsys::Directory d;
+ if (!d.Load(data_dir) || d.GetNumberOfFiles() == 0) {
+ return;
+ }
+
+ xml.StartElement("Commands");
+
+ for (unsigned int i = 0; i < d.GetNumberOfFiles(); i++) {
+ std::string fpath = d.GetFilePath(i);
+ std::string fname = d.GetFile(i);
+ if (fname.rfind('.', 0) == 0) {
+ continue;
+ }
+ this->ConvertInstrumentationJSONFileToXML(fpath, xml);
+ }
+
+ xml.EndElement(); // Commands
+}
+
+bool cmCTest::ConvertInstrumentationJSONFileToXML(std::string const& fpath,
+ cmXMLWriter& xml)
+{
+ Json::Value root;
+ this->Impl->parseState = cmJSONState(fpath, &root);
+ if (!this->Impl->parseState.errors.empty()) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ this->Impl->parseState.GetErrorMessage(true) << std::endl);
+ return false;
+ }
+
+ if (root.type() != Json::objectValue) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Expected object, found " << root.type() << " for "
+ << root.asString() << std::endl);
+ return false;
+ }
+
+ std::vector<std::string> required_members = {
+ "command",
+ "role",
+ "dynamicSystemInformation",
+ };
+ for (std::string const& required_member : required_members) {
+ if (!root.isMember(required_member)) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ fpath << " is missing the '" << required_member << "' key"
+ << std::endl);
+ return false;
+ }
+ }
+
+ // Do not record command-level data for Test.xml files because
+ // it is redundant with information actually captured by CTest.
+ bool generating_test_xml = root["role"] == "test";
+ if (!generating_test_xml) {
+ std::string element_name = root["role"].asString();
+ element_name[0] = static_cast<char>(std::toupper(element_name[0]));
+ xml.StartElement(element_name);
+ std::vector<std::string> keys = root.getMemberNames();
+ for (auto const& key : keys) {
+ auto key_type = root[key].type();
+ if (key_type == Json::objectValue || key_type == Json::arrayValue) {
+ continue;
+ }
+ if (key == "role" || key == "target" || key == "targetType" ||
+ key == "targetLabels") {
+ continue;
+ }
+ // Truncate the full command line if verbose instrumentation
+ // was not requested.
+ if (key == "command" && !this->GetUseVerboseInstrumentation()) {
+ std::string command_str = root[key].asString();
+ std::string truncated = command_str.substr(0, command_str.find(' '));
+ if (command_str != truncated) {
+ truncated = cmStrCat(truncated, " (truncated)");
+ }
+ xml.Attribute(key.c_str(), truncated);
+ continue;
+ }
+ xml.Attribute(key.c_str(), root[key].asString());
+ }
+ }
+
+ // Record dynamicSystemInformation section as XML.
+ auto dynamic_information = root["dynamicSystemInformation"];
+ std::vector<std::string> keys = dynamic_information.getMemberNames();
+ for (auto const& key : keys) {
+ std::string measurement_name = key;
+ measurement_name[0] = static_cast<char>(std::toupper(measurement_name[0]));
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "numeric/double");
+ xml.Attribute("name", measurement_name);
+ xml.Element("Value", dynamic_information[key].asString());
+ xml.EndElement(); // NamedMeasurement
+ }
+
+ if (!generating_test_xml) {
+ xml.EndElement(); // role
+ }
+
+ cmSystemTools::RemoveFile(fpath);
+ return true;
+}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index c6bfede..fd6d8b1 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -21,6 +21,7 @@
class cmake;
class cmGeneratedFileStream;
+class cmInstrumentation;
class cmMakefile;
class cmValue;
class cmXMLWriter;
@@ -391,6 +392,11 @@
bool StartLogFile(char const* name, int submitIndex,
cmGeneratedFileStream& xofs);
+ void ConvertInstrumentationSnippetsToXML(cmXMLWriter& xml,
+ std::string const& subdir);
+ bool ConvertInstrumentationJSONFileToXML(std::string const& fpath,
+ cmXMLWriter& xml);
+
void AddSiteProperties(cmXMLWriter& xml, cmake* cm);
bool GetInteractiveDebugMode() const;
@@ -433,6 +439,9 @@
cmCTestTestOptions const& GetTestOptions() const;
std::vector<std::string> GetCommandLineHttpHeaders() const;
+ cmInstrumentation& GetInstrumentation();
+ bool GetUseVerboseInstrumentation() const;
+
private:
int GenerateNotesFile(cmake* cm, std::string const& files);
@@ -471,7 +480,7 @@
int RunCMakeAndTest();
int RunScripts(std::vector<std::pair<std::string, bool>> const& scripts);
- int ExecuteTests();
+ int ExecuteTests(std::vector<std::string> const& args);
struct Private;
std::unique_ptr<Private> Impl;
diff --git a/Source/cmExportPackageInfoGenerator.cxx b/Source/cmExportPackageInfoGenerator.cxx
index 211347e..8616e10 100644
--- a/Source/cmExportPackageInfoGenerator.cxx
+++ b/Source/cmExportPackageInfoGenerator.cxx
@@ -127,9 +127,22 @@
{
if (!this->Requirements.empty()) {
Json::Value& requirements = package["requires"];
+
+ // Build description for each requirement.
for (auto const& requirement : this->Requirements) {
+ auto data = Json::Value{ Json::objectValue };
+
+ // Add required components.
+ if (!requirement.second.empty()) {
+ auto components = Json::Value{ Json::arrayValue };
+ for (std::string const& component : requirement.second) {
+ components.append(component);
+ }
+ data["components"] = components;
+ }
+
// TODO: version, hint
- requirements[requirement] = Json::Value{};
+ requirements[requirement.first] = data;
}
}
}
@@ -257,10 +270,10 @@
return false;
}
+ std::string component = linkedName.substr(prefix.length());
+ this->LinkTargets.emplace(linkedName, cmStrCat(pkgName, ':', component));
// TODO: Record package version, hint.
- this->Requirements.emplace(pkgName);
- this->LinkTargets.emplace(
- linkedName, cmStrCat(pkgName, ':', linkedName.substr(prefix.length())));
+ this->Requirements[pkgName].emplace(std::move(component));
return true;
}
@@ -278,16 +291,13 @@
return false;
}
- auto pkgName =
- cm::string_view{ linkNamespace.data(), linkNamespace.size() - 2 };
-
+ std::string pkgName{ linkNamespace.data(), linkNamespace.size() - 2 };
+ std::string component = linkedTarget->GetExportName();
if (pkgName == this->GetPackageName()) {
- this->LinkTargets.emplace(linkedName,
- cmStrCat(':', linkedTarget->GetExportName()));
+ this->LinkTargets.emplace(linkedName, cmStrCat(':', component));
} else {
- this->Requirements.emplace(pkgName);
- this->LinkTargets.emplace(
- linkedName, cmStrCat(pkgName, ':', linkedTarget->GetExportName()));
+ this->LinkTargets.emplace(linkedName, cmStrCat(pkgName, ':', component));
+ this->Requirements[pkgName].emplace(std::move(component));
}
return true;
}
diff --git a/Source/cmExportPackageInfoGenerator.h b/Source/cmExportPackageInfoGenerator.h
index 6fe1e35..5014252 100644
--- a/Source/cmExportPackageInfoGenerator.h
+++ b/Source/cmExportPackageInfoGenerator.h
@@ -110,5 +110,5 @@
std::vector<std::string> DefaultConfigurations;
std::map<std::string, std::string> LinkTargets;
- std::set<std::string> Requirements;
+ std::map<std::string, std::set<std::string>> Requirements;
};
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 7720485..2c51cf0 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -532,6 +532,7 @@
this->DeprecatedFindModules["Boost"] = cmPolicies::CMP0167;
this->DeprecatedFindModules["CUDA"] = cmPolicies::CMP0146;
this->DeprecatedFindModules["Dart"] = cmPolicies::CMP0145;
+ this->DeprecatedFindModules["GCCXML"] = cmPolicies::CMP0188;
this->DeprecatedFindModules["PythonInterp"] = cmPolicies::CMP0148;
this->DeprecatedFindModules["PythonLibs"] = cmPolicies::CMP0148;
this->DeprecatedFindModules["Qt"] = cmPolicies::CMP0084;
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index e54a8b7..0e8fa74 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -25,6 +25,7 @@
DeprecatedModules["FindBoost"] = cmPolicies::CMP0167;
DeprecatedModules["FindCUDA"] = cmPolicies::CMP0146;
DeprecatedModules["FindDart"] = cmPolicies::CMP0145;
+ DeprecatedModules["FindGCCXML"] = cmPolicies::CMP0188;
DeprecatedModules["FindPythonInterp"] = cmPolicies::CMP0148;
DeprecatedModules["FindPythonLibs"] = cmPolicies::CMP0148;
DeprecatedModules["WriteCompilerDetectionHeader"] = cmPolicies::CMP0120;
diff --git a/Source/cmInstrumentation.cxx b/Source/cmInstrumentation.cxx
index 6dffc4c..2c4414f 100644
--- a/Source/cmInstrumentation.cxx
+++ b/Source/cmInstrumentation.cxx
@@ -20,10 +20,12 @@
#include "cmCryptoHash.h"
#include "cmExperimental.h"
#include "cmInstrumentationQuery.h"
+#include "cmJSONState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmUVProcessChain.h"
+#include "cmValue.h"
cmInstrumentation::cmInstrumentation(std::string const& binary_dir)
{
@@ -53,6 +55,75 @@
this->hasQuery = this->hasQuery ||
this->ReadJSONQueries(cmStrCat(this->userTimingDirv1, "/query"));
}
+
+ std::string envVal;
+ if (cmSystemTools::GetEnv("CTEST_USE_INSTRUMENTATION", envVal) &&
+ !cmIsOff(envVal)) {
+ if (cmSystemTools::GetEnv("CTEST_EXPERIMENTAL_INSTRUMENTATION", envVal)) {
+ std::string const uuid = cmExperimental::DataForFeature(
+ cmExperimental::Feature::Instrumentation)
+ .Uuid;
+ if (envVal == uuid) {
+ this->AddHook(cmInstrumentationQuery::Hook::PrepareForCDash);
+ this->AddQuery(
+ cmInstrumentationQuery::Query::DynamicSystemInformation);
+ this->cdashDir = cmStrCat(this->timingDirv1, "/cdash");
+ cmSystemTools::MakeDirectory(this->cdashDir);
+ cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/configure"));
+ cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/build"));
+ cmSystemTools::MakeDirectory(
+ cmStrCat(this->cdashDir, "/build/commands"));
+ cmSystemTools::MakeDirectory(
+ cmStrCat(this->cdashDir, "/build/targets"));
+ cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/test"));
+ this->cdashSnippetsMap = { {
+ "configure",
+ "configure",
+ },
+ {
+ "generate",
+ "configure",
+ },
+ {
+ "compile",
+ "build",
+ },
+ {
+ "link",
+ "build",
+ },
+ {
+ "custom",
+ "build",
+ },
+ {
+ "build",
+ "skip",
+ },
+ {
+ "cmakeBuild",
+ "build",
+ },
+ {
+ "cmakeInstall",
+ "build",
+ },
+ {
+ "install",
+ "build",
+ },
+ {
+ "ctest",
+ "build",
+ },
+ {
+ "test",
+ "test",
+ } };
+ this->hasQuery = true;
+ }
+ }
+ }
}
bool cmInstrumentation::ReadJSONQueries(std::string const& directory)
@@ -211,6 +282,11 @@
cmSystemTools::OUTPUT_PASSTHROUGH);
}
+ // Special case for CDash collation
+ if (this->HasHook(cmInstrumentationQuery::Hook::PrepareForCDash)) {
+ this->PrepareDataForCDash(directory, index_path);
+ }
+
// Delete files
for (auto const& f : index["snippets"]) {
cmSystemTools::RemoveFile(cmStrCat(directory, "/", f.asString()));
@@ -308,7 +384,7 @@
ftmp.close();
}
-int cmInstrumentation::InstrumentTest(
+std::string cmInstrumentation::InstrumentTest(
std::string const& name, std::string const& command,
std::vector<std::string> const& args, int64_t result,
std::chrono::steady_clock::time_point steadyStart,
@@ -331,11 +407,11 @@
this->InsertDynamicSystemInformation(root, "after");
}
- std::string const& file_name =
+ std::string file_name =
cmStrCat("test-", this->ComputeSuffixHash(command_str),
this->ComputeSuffixTime(), ".json");
this->WriteInstrumentationJson(root, "data", file_name);
- return 1;
+ return file_name;
}
void cmInstrumentation::GetPreTestStats()
@@ -547,3 +623,107 @@
this->CollectTimingData(cmInstrumentationQuery::Hook::PostBuild);
return ret;
}
+
+void cmInstrumentation::AddHook(cmInstrumentationQuery::Hook hook)
+{
+ this->hooks.insert(hook);
+}
+
+void cmInstrumentation::AddQuery(cmInstrumentationQuery::Query query)
+{
+ this->queries.insert(query);
+}
+
+std::string const& cmInstrumentation::GetCDashDir()
+{
+ return this->cdashDir;
+}
+
+/** Copy the snippets referred to by an index file to a separate
+ * directory where they will be parsed for submission to CDash.
+ **/
+void cmInstrumentation::PrepareDataForCDash(std::string const& data_dir,
+ std::string const& index_path)
+{
+ Json::Value root;
+ std::string error_msg;
+ cmJSONState parseState = cmJSONState(index_path, &root);
+ if (!parseState.errors.empty()) {
+ cmSystemTools::Error(parseState.GetErrorMessage(true));
+ return;
+ }
+
+ if (!root.isObject()) {
+ error_msg =
+ cmStrCat("Expected index file ", index_path, " to contain an object");
+ cmSystemTools::Error(error_msg);
+ return;
+ }
+
+ if (!root.isMember("snippets")) {
+ error_msg = cmStrCat("Expected index file ", index_path,
+ " to have a key 'snippets'");
+ cmSystemTools::Error(error_msg);
+ return;
+ }
+
+ std::string dst_dir;
+ Json::Value snippets = root["snippets"];
+ for (auto const& snippet : snippets) {
+ // Parse the role of this snippet.
+ std::string snippet_str = snippet.asString();
+ std::string snippet_path = cmStrCat(data_dir, '/', snippet_str);
+ Json::Value snippet_root;
+ parseState = cmJSONState(snippet_path, &snippet_root);
+ if (!parseState.errors.empty()) {
+ cmSystemTools::Error(parseState.GetErrorMessage(true));
+ continue;
+ }
+ if (!snippet_root.isObject()) {
+ error_msg = cmStrCat("Expected snippet file ", snippet_path,
+ " to contain an object");
+ cmSystemTools::Error(error_msg);
+ continue;
+ }
+ if (!snippet_root.isMember("role")) {
+ error_msg = cmStrCat("Expected snippet file ", snippet_path,
+ " to have a key 'role'");
+ cmSystemTools::Error(error_msg);
+ continue;
+ }
+
+ std::string snippet_role = snippet_root["role"].asString();
+ auto map_element = this->cdashSnippetsMap.find(snippet_role);
+ if (map_element == this->cdashSnippetsMap.end()) {
+ std::string message =
+ "Unexpected snippet type encountered: " + snippet_role;
+ cmSystemTools::Message(message, "Warning");
+ continue;
+ }
+
+ if (map_element->second == "skip") {
+ continue;
+ }
+
+ if (map_element->second == "build") {
+ // We organize snippets on a per-target basis (when possible)
+ // for Build.xml.
+ if (snippet_root.isMember("target")) {
+ dst_dir = cmStrCat(this->cdashDir, "/build/targets/",
+ snippet_root["target"].asString());
+ cmSystemTools::MakeDirectory(dst_dir);
+ } else {
+ dst_dir = cmStrCat(this->cdashDir, "/build/commands");
+ }
+ } else {
+ dst_dir = cmStrCat(this->cdashDir, '/', map_element->second);
+ }
+
+ std::string dst = cmStrCat(dst_dir, '/', snippet_str);
+ cmsys::Status copied = cmSystemTools::CopyFileAlways(snippet_path, dst);
+ if (!copied) {
+ error_msg = cmStrCat("Failed to copy ", snippet_path, " to ", dst);
+ cmSystemTools::Error(error_msg);
+ }
+ }
+}
diff --git a/Source/cmInstrumentation.h b/Source/cmInstrumentation.h
index 3a2f9d9..0382495 100644
--- a/Source/cmInstrumentation.h
+++ b/Source/cmInstrumentation.h
@@ -29,11 +29,13 @@
cm::optional<std::map<std::string, std::string>> arrayOptions =
cm::nullopt,
bool reloadQueriesAfterCommand = false);
- int InstrumentTest(std::string const& name, std::string const& command,
- std::vector<std::string> const& args, int64_t result,
- std::chrono::steady_clock::time_point steadyStart,
- std::chrono::system_clock::time_point systemStart,
- std::string config);
+ std::string InstrumentTest(std::string const& name,
+ std::string const& command,
+ std::vector<std::string> const& args,
+ int64_t result,
+ std::chrono::steady_clock::time_point steadyStart,
+ std::chrono::system_clock::time_point systemStart,
+ std::string config);
void GetPreTestStats();
void LoadQueries();
bool HasQuery() const;
@@ -49,7 +51,10 @@
int CollectTimingData(cmInstrumentationQuery::Hook hook);
int SpawnBuildDaemon();
int CollectTimingAfterBuild(int ppid);
+ void AddHook(cmInstrumentationQuery::Hook hook);
+ void AddQuery(cmInstrumentationQuery::Query query);
std::string errorMsg;
+ std::string const& GetCDashDir();
private:
void WriteInstrumentationJson(Json::Value& index,
@@ -66,13 +71,17 @@
static std::string GetCommandStr(std::vector<std::string> const& args);
static std::string ComputeSuffixHash(std::string const& command_str);
static std::string ComputeSuffixTime();
+ void PrepareDataForCDash(std::string const& data_dir,
+ std::string const& index_path);
std::string binaryDir;
std::string timingDirv1;
std::string userTimingDirv1;
+ std::string cdashDir;
std::set<cmInstrumentationQuery::Query> queries;
std::set<cmInstrumentationQuery::Hook> hooks;
std::vector<std::string> callbacks;
std::vector<std::string> queryFiles;
+ std::map<std::string, std::string> cdashSnippetsMap;
Json::Value preTestStats;
bool hasQuery = false;
};
diff --git a/Source/cmInstrumentationQuery.cxx b/Source/cmInstrumentationQuery.cxx
index bee8b37..88872f6 100644
--- a/Source/cmInstrumentationQuery.cxx
+++ b/Source/cmInstrumentationQuery.cxx
@@ -19,8 +19,9 @@
"staticSystemInformation", "dynamicSystemInformation"
};
std::vector<std::string> const cmInstrumentationQuery::HookString{
- "postGenerate", "preBuild", "postBuild", "preCMakeBuild",
- "postCMakeBuild", "postTest", "postInstall", "manual"
+ "postGenerate", "preBuild", "postBuild",
+ "preCMakeBuild", "postCMakeBuild", "postTest",
+ "postInstall", "prepareForCDash", "manual"
};
namespace ErrorMessages {
diff --git a/Source/cmInstrumentationQuery.h b/Source/cmInstrumentationQuery.h
index 93a9caf..b8d8936 100644
--- a/Source/cmInstrumentationQuery.h
+++ b/Source/cmInstrumentationQuery.h
@@ -28,6 +28,7 @@
PostCMakeBuild,
PostTest,
PostInstall,
+ PrepareForCDash,
Manual
};
static std::vector<std::string> const HookString;
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 5f5f383..c244975 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -558,7 +558,12 @@
WARN) \
SELECT(POLICY, CMP0186, \
"Regular expressions match ^ at most once in repeated searches.", 4, \
- 1, 0, WARN)
+ 1, 0, WARN) \
+ SELECT(POLICY, CMP0187, \
+ "Include source file without an extension after the same name with " \
+ "an extension.", \
+ 4, 1, 0, WARN) \
+ SELECT(POLICY, CMP0188, "The FindGCCXML module is removed.", 4, 1, 0, WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index b7b9770..c9ba19e 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -9,11 +9,19 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-cmSourceFileLocation::cmSourceFileLocation() = default;
+// if CMP0187 and CMP0115 are NEW, then we assume that source files that do not
+// include a file extension are not ambiguous but intentionally do not have an
+// extension.
+bool NoAmbiguousExtensions(cmMakefile const& makefile)
+{
+ return makefile.GetPolicyStatus(cmPolicies::CMP0115) == cmPolicies::NEW &&
+ makefile.GetPolicyStatus(cmPolicies::CMP0187) == cmPolicies::NEW;
+}
cmSourceFileLocation::cmSourceFileLocation(cmSourceFileLocation const& loc)
: Makefile(loc.Makefile)
@@ -30,7 +38,12 @@
: Makefile(mf)
{
this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name);
- this->AmbiguousExtension = true;
+ // If ambiguous extensions are allowed then the extension is assumed to be
+ // ambiguous unless the name has an extension, in which case
+ // `UpdateExtension` will update this. If ambiguous extensions are not
+ // allowed, then set this to false as the file extension must be provided or
+ // the file doesn't have an extension.
+ this->AmbiguousExtension = !NoAmbiguousExtensions(*mf);
this->Directory = cmSystemTools::GetFilenamePath(name);
if (cmSystemTools::FileIsFullPath(this->Directory)) {
this->Directory = cmSystemTools::CollapseFullPath(this->Directory);
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index f923ba6..19ce9f6 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -251,15 +251,7 @@
std::string output;
if (re.find(input)) {
status.GetMakefile().StoreMatches(re);
- std::string::size_type l = re.start();
- std::string::size_type r = re.end();
- if (r - l == 0) {
- std::string e = "sub-command REGEX, mode MATCH regex \"" + regex +
- "\" matched an empty string.";
- status.SetError(e);
- return false;
- }
- output = input.substr(l, r - l);
+ output = re.match();
}
// Store the output in the provided variable.
@@ -298,22 +290,24 @@
// Scan through the input for all matches.
std::string output;
std::string::size_type base = 0;
- while (re.find(input, base, optAnchor)) {
+ unsigned optNonEmpty = 0;
+ while (re.find(input, base, optAnchor | optNonEmpty)) {
status.GetMakefile().ClearMatches();
status.GetMakefile().StoreMatches(re);
- std::string::size_type l = re.start();
- std::string::size_type r = re.end();
- if (r - l == 0) {
- std::string e = "sub-command REGEX, mode MATCHALL regex \"" + regex +
- "\" matched an empty string.";
- status.SetError(e);
- return false;
- }
- if (!output.empty()) {
+ if (!output.empty() || optNonEmpty) {
output += ";";
}
output += re.match();
- base = r;
+ base = re.end();
+
+ if (re.start() == input.length()) {
+ break;
+ }
+ if (re.start() == re.end()) {
+ optNonEmpty = cmsys::RegularExpression::NONEMPTY_AT_OFFSET;
+ } else {
+ optNonEmpty = 0;
+ }
}
// Store the output in the provided variable.
diff --git a/Source/cmStringReplaceHelper.cxx b/Source/cmStringReplaceHelper.cxx
index 5cd159e..025dfc7 100644
--- a/Source/cmStringReplaceHelper.cxx
+++ b/Source/cmStringReplaceHelper.cxx
@@ -33,25 +33,17 @@
}
// Scan through the input for all matches.
+ auto& re = this->RegularExpression;
std::string::size_type base = 0;
- while (this->RegularExpression.find(input, base, optAnchor)) {
+ unsigned optNonEmpty = 0;
+ while (re.find(input, base, optAnchor | optNonEmpty)) {
if (this->Makefile) {
this->Makefile->ClearMatches();
- this->Makefile->StoreMatches(this->RegularExpression);
+ this->Makefile->StoreMatches(re);
}
- auto l2 = this->RegularExpression.start();
- auto r = this->RegularExpression.end();
// Concatenate the part of the input that was not matched.
- output += input.substr(base, l2 - base);
-
- // Make sure the match had some text.
- if (r - l2 == 0) {
- std::ostringstream error;
- error << "regex \"" << this->RegExString << "\" matched an empty string";
- this->ErrorString = error.str();
- return false;
- }
+ output += input.substr(base, re.start() - base);
// Concatenate the replacement for the match.
for (auto const& replacement : this->Replacements) {
@@ -61,10 +53,7 @@
} else {
// Replace with part of the match.
auto n = replacement.Number;
- auto start = this->RegularExpression.start(n);
- if (start != std::string::npos) {
- output += this->RegularExpression.match(n);
- } else {
+ if (n > re.num_groups()) {
std::ostringstream error;
error << "replace expression \"" << this->ReplaceExpression
<< "\" contains an out-of-range escape for regex \""
@@ -72,11 +61,21 @@
this->ErrorString = error.str();
return false;
}
+ output += re.match(n);
}
}
// Move past the match.
- base = r;
+ base = re.end();
+
+ if (re.start() == input.length()) {
+ break;
+ }
+ if (re.start() == re.end()) {
+ optNonEmpty = cmsys::RegularExpression::NONEMPTY_AT_OFFSET;
+ } else {
+ optNonEmpty = 0;
+ }
}
// Concatenate the text after the last match.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 78d4655..f880884 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2624,7 +2624,7 @@
cmSystemTools::Error(this->Instrumentation->errorMsg);
return 1;
}
- std::function<int()> doConfigure = [this]() -> int {
+ auto doConfigure = [this]() -> int {
this->GlobalGenerator->Configure();
return 0;
};
@@ -3023,7 +3023,7 @@
auto startTime = std::chrono::steady_clock::now();
#if !defined(CMAKE_BOOTSTRAP)
auto profilingRAII = this->CreateProfilingEntry("project", "generate");
- std::function<int()> doGenerate = [this]() -> int {
+ auto doGenerate = [this]() -> int {
if (!this->GlobalGenerator->Compute()) {
return -1;
}
@@ -3720,7 +3720,8 @@
int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
std::string config, std::vector<std::string> nativeOptions,
cmBuildOptions& buildOptions, bool verbose,
- std::string const& presetName, bool listPresets)
+ std::string const& presetName, bool listPresets,
+ std::vector<std::string> const& args)
{
this->SetHomeDirectory("");
this->SetHomeOutputDirectory("");
@@ -3959,16 +3960,38 @@
return 1;
}
+#if !defined(CMAKE_BOOTSTRAP)
+ cmInstrumentation instrumentation(dir);
+ if (!instrumentation.errorMsg.empty()) {
+ cmSystemTools::Error(instrumentation.errorMsg);
+ return 1;
+ }
+ instrumentation.CollectTimingData(
+ cmInstrumentationQuery::Hook::PreCMakeBuild);
+#endif
+
this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs);
std::stringstream ostr;
// `cmGlobalGenerator::Build` logs metadata about what directory and commands
// are being executed to the `output` parameter. If CMake is verbose, print
// this out.
std::ostream& verbose_ostr = verbose ? std::cout : ostr;
- int buildresult = this->GlobalGenerator->Build(
- jobs, "", dir, projName, targets, verbose_ostr, "", config, buildOptions,
- verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH,
- nativeOptions);
+ auto doBuild = [this, jobs, dir, projName, targets, &verbose_ostr, config,
+ buildOptions, verbose, nativeOptions]() -> int {
+ return this->GlobalGenerator->Build(
+ jobs, "", dir, projName, targets, verbose_ostr, "", config, buildOptions,
+ verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH,
+ nativeOptions);
+ };
+
+#if !defined(CMAKE_BOOTSTRAP)
+ int buildresult =
+ instrumentation.InstrumentCommand("cmakeBuild", args, doBuild);
+ instrumentation.CollectTimingData(
+ cmInstrumentationQuery::Hook::PostCMakeBuild);
+#else
+ int buildresult = doBuild();
+#endif
return buildresult;
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 49231f4..829bb7c 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -640,7 +640,8 @@
int Build(int jobs, std::string dir, std::vector<std::string> targets,
std::string config, std::vector<std::string> nativeOptions,
cmBuildOptions& buildOptions, bool verbose,
- std::string const& presetName, bool listPresets);
+ std::string const& presetName, bool listPresets,
+ std::vector<std::string> const& args);
//! run the --open option
bool Open(std::string const& dir, bool dryRun);
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 80a0ce8..60b59ad 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -705,27 +705,12 @@
cmakemainProgressCallback(msg, prog, &cm);
});
- cmInstrumentation instrumentation(dir);
- if (!instrumentation.errorMsg.empty()) {
- cmSystemTools::Error(instrumentation.errorMsg);
- return 1;
- }
cmBuildOptions buildOptions(cleanFirst, false, resolveMode);
- std::function<int()> doBuild = [&cm, &jobs, &dir, &targets, &config,
- &nativeOptions, &buildOptions, &verbose,
- &presetName, &listPresets]() {
- return cm.Build(jobs, dir, std::move(targets), std::move(config),
- std::move(nativeOptions), buildOptions, verbose,
- presetName, listPresets);
- };
- instrumentation.CollectTimingData(
- cmInstrumentationQuery::Hook::PreCMakeBuild);
std::vector<std::string> cmd;
cm::append(cmd, av, av + ac);
- int ret = instrumentation.InstrumentCommand("cmakeBuild", cmd, doBuild);
- instrumentation.CollectTimingData(
- cmInstrumentationQuery::Hook::PostCMakeBuild);
- return ret;
+ return cm.Build(jobs, dir, std::move(targets), std::move(config),
+ std::move(nativeOptions), buildOptions, verbose, presetName,
+ listPresets, cmd);
#endif
}
@@ -986,8 +971,7 @@
}
}
- std::function<int()> doInstall = [&handler, &verbose, &jobs,
- &instrumentation]() -> int {
+ auto doInstall = [&handler, &verbose, &jobs, &instrumentation]() -> int {
int ret_ = 0;
if (handler.IsParallel()) {
ret_ = handler.Install(jobs, instrumentation);
diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in
index 6a94cc5..ca2ee02 100644
--- a/Tests/CMakeTests/StringTest.cmake.in
+++ b/Tests/CMakeTests/StringTest.cmake.in
@@ -84,7 +84,7 @@
# Execute each test listed in StringTestScript.cmake:
#
set(scriptname "@CMAKE_CURRENT_SOURCE_DIR@/StringTestScript.cmake")
-set(number_of_tests_expected 72)
+set(number_of_tests_expected 70)
include("@CMAKE_CURRENT_SOURCE_DIR@/ExecuteScriptTests.cmake")
execute_all_script_tests(${scriptname} number_of_tests_executed)
diff --git a/Tests/CMakeTests/StringTestScript.cmake b/Tests/CMakeTests/StringTestScript.cmake
index 7c45857..84b404c 100644
--- a/Tests/CMakeTests/StringTestScript.cmake
+++ b/Tests/CMakeTests/StringTestScript.cmake
@@ -73,9 +73,6 @@
elseif(testname STREQUAL regex_match_bad_regex) # fail
string(REGEX MATCH "(.*" v input)
-elseif(testname STREQUAL regex_match_empty_string) # fail
- string(REGEX MATCH "x*" v "")
-
elseif(testname STREQUAL regex_match_no_match) # pass
string(REGEX MATCH "xyz" v "abc")
message(STATUS "v='${v}'")
@@ -87,9 +84,6 @@
elseif(testname STREQUAL regex_matchall_bad_regex) # fail
string(REGEX MATCHALL "(.*" v input)
-elseif(testname STREQUAL regex_matchall_empty_string) # fail
- string(REGEX MATCHALL "x*" v "")
-
elseif(testname STREQUAL regex_replace_ends_with_backslash) # fail
string(REGEX REPLACE "input" "output\\" v input1 input2 input3 input4)
@@ -107,15 +101,16 @@
elseif(testname STREQUAL regex_replace_bad_regex) # fail
string(REGEX REPLACE "this (.*" "with that" v input)
-elseif(testname STREQUAL regex_replace_empty_string) # fail
- string(REGEX REPLACE "x*" "that" v "")
-
elseif(testname STREQUAL regex_replace_index_too_small) # fail
string(REGEX REPLACE "^this (.*)$" "with \\1 \\-1" v "this input")
elseif(testname STREQUAL regex_replace_index_too_large) # fail
string(REGEX REPLACE "^this (.*)$" "with \\1 \\2" v "this input")
+elseif(testname STREQUAL regex_replace_index_no_match) # pass
+ string(REGEX REPLACE "^(this (.*)|(that .*))$" "with \\1 \\2 \\3" v "this input")
+ message(STATUS "v='${v}'")
+
elseif(testname STREQUAL compare_no_mode) # fail
string(COMPARE)
diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-build-result.txt b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-build-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-build-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-stderr.txt b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-stderr.txt
new file mode 100644
index 0000000..ac1885a
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Deprecation Warning at CMP0187-NEW-CMP0115-OLD\.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0115 will be removed from a future version
+ of CMake\.
diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD.cmake b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD.cmake
new file mode 100644
index 0000000..ee45dfb
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0115 OLD)
+cmake_policy(SET CMP0187 NEW)
+
+include(CMP0187.cmake)
diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-build-result.txt b/Tests/RunCMake/CMP0187/CMP0187-NEW-build-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-build-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW.cmake b/Tests/RunCMake/CMP0187/CMP0187-NEW.cmake
new file mode 100644
index 0000000..a140325
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-NEW.cmake
@@ -0,0 +1,3 @@
+cmake_policy(SET CMP0187 NEW)
+
+include(CMP0187.cmake)
diff --git a/Tests/RunCMake/CMP0187/CMP0187-OLD-build-result.txt b/Tests/RunCMake/CMP0187/CMP0187-OLD-build-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-OLD-build-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CMP0187/CMP0187-OLD.cmake b/Tests/RunCMake/CMP0187/CMP0187-OLD.cmake
new file mode 100644
index 0000000..d48b4bb
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187-OLD.cmake
@@ -0,0 +1,3 @@
+cmake_policy(SET CMP0187 OLD)
+
+include(CMP0187.cmake)
diff --git a/Tests/RunCMake/CMP0187/CMP0187.cmake b/Tests/RunCMake/CMP0187/CMP0187.cmake
new file mode 100644
index 0000000..029d0c9
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMP0187.cmake
@@ -0,0 +1,4 @@
+add_custom_command(OUTPUT z.h COMMAND ${CMAKE_COMMAND} -E true)
+add_custom_command(OUTPUT z COMMAND ${CMAKE_COMMAND} -E false)
+
+add_library(lib INTERFACE z z.h)
diff --git a/Tests/RunCMake/CMP0187/CMakeLists.txt b/Tests/RunCMake/CMP0187/CMakeLists.txt
new file mode 100644
index 0000000..7e8fde0
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 4.0)
+
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0187/RunCMakeTest.cmake b/Tests/RunCMake/CMP0187/RunCMakeTest.cmake
new file mode 100644
index 0000000..f28cc70
--- /dev/null
+++ b/Tests/RunCMake/CMP0187/RunCMakeTest.cmake
@@ -0,0 +1,34 @@
+include(RunCMake)
+
+block()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0187-NEW-build)
+ run_cmake_with_options(CMP0187-NEW "-DCMAKE_POLICY_DEFAULT_CMP0187=NEW")
+
+ if(RunCMake_GENERATOR MATCHES "Ninja.*")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ # -n: dry-run to avoid actually compiling, -v: verbose to capture executed command
+ run_cmake_command(CMP0187-NEW-build ${CMAKE_COMMAND} --build .)
+ endif()
+endblock()
+
+block()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0187-OLD-build)
+ run_cmake_with_options(CMP0187-OLD "-DCMAKE_POLICY_DEFAULT_CMP0187=OLD")
+
+ if(RunCMake_GENERATOR MATCHES "Ninja.*")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ # -n: dry-run to avoid actually compiling, -v: verbose to capture executed command
+ run_cmake_command(CMP0187-OLD-build ${CMAKE_COMMAND} --build .)
+ endif()
+endblock()
+
+block()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0187-NEW-CMP0115-OLD-build)
+ run_cmake(CMP0187-NEW-CMP0115-OLD)
+
+ if(RunCMake_GENERATOR MATCHES "Ninja.*")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ # -n: dry-run to avoid actually compiling, -v: verbose to capture executed command
+ run_cmake_command(CMP0187-NEW-CMP0115-OLD-build ${CMAKE_COMMAND} --build .)
+ endif()
+endblock()
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index e664ca3..fdf26ce 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -179,6 +179,7 @@
add_RunCMake_test(CMP0170)
add_RunCMake_test(CMP0171)
add_RunCMake_test(CMP0173)
+add_RunCMake_test(CMP0187)
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
@@ -396,6 +397,7 @@
add_RunCMake_test(CompilerTest ${CMake_TEST_LANG_VARS})
set_property(TEST RunCMake.CompilerTest APPEND PROPERTY LABELS "CUDA" "HIP" "ISPC" "Fortran")
add_RunCMake_test(Configure -DMSVC_IDE=${MSVC_IDE})
+add_RunCMake_test(CpsExportImport)
add_RunCMake_test(DisallowedCommands)
if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(ExportCompileCommands)
@@ -605,6 +607,9 @@
add_RunCMake_test(ctest_environment)
add_RunCMake_test(ctest_empty_binary_directory)
add_RunCMake_test(ctest_fixtures)
+if(CMAKE_GENERATOR MATCHES "Make|Ninja")
+ add_RunCMake_test(ctest_instrumentation)
+endif()
add_RunCMake_test(define_property)
add_RunCMake_test(file -DCYGWIN=${CYGWIN} -DMSYS=${MSYS})
add_RunCMake_test(file-CHMOD -DMSYS=${MSYS})
diff --git a/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt b/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt
index 2960eeb..b8e2639 100644
--- a/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt
+++ b/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt
@@ -13,6 +13,10 @@
"cmake-@version@-macos-universal\.tar\.gz"
"cmake-@version@-macos10\.10-universal\.dmg"
"cmake-@version@-macos10\.10-universal\.tar\.gz"
+"cmake-@version@-sunos-i386\.sh"
+"cmake-@version@-sunos-i386\.tar\.gz"
+"cmake-@version@-sunos-sparc\.sh"
+"cmake-@version@-sunos-sparc\.tar\.gz"
"cmake-@version@-windows-i386\.msi"
"cmake-@version@-windows-i386\.zip"
"cmake-@version@-windows-x86_64\.msi"
@@ -28,6 +32,8 @@
"cmake-@version@-macos-universal\.dmg"
-- query: \.files\[\] \| select\(\(\.os\[\] \| \. == "macos10\.10"\) and \(\.class == "archive"\)\) \| \.name
"cmake-@version@-macos10\.10-universal\.tar\.gz"
+-- query: \.files\[\] \| select\(\(\.os\[\] \| \. == "sunos"\) and \(\.architecture\[\] \| \. == "sparc"\) and \(\.class == "archive"\)\) \| \.name
+"cmake-@version@-sunos-sparc\.tar\.gz"
-- query: \.files\[\] \| select\(\(\.os\[\] \| \. == "windows"\) and \(\.architecture\[\] \| \. == "i386"\) and \(\.class == "installer"\)\) \| \.name
"cmake-@version@-windows-i386\.msi"
-- query: \.files\[\] \| select\(\.architecture\[\] \| \. == "x86_64"\) \| \.name
diff --git a/Tests/RunCMake/CMakeRelease/FileTable.cmake b/Tests/RunCMake/CMakeRelease/FileTable.cmake
index f46535c..a579457 100644
--- a/Tests/RunCMake/CMakeRelease/FileTable.cmake
+++ b/Tests/RunCMake/CMakeRelease/FileTable.cmake
@@ -11,6 +11,7 @@
".files[] | select(.os[] | . == \"source\") | .name"
".files[] | select((.os[] | . == \"macOS\") and (.class == \"volume\")) | .name"
".files[] | select((.os[] | . == \"macos10.10\") and (.class == \"archive\")) | .name"
+ ".files[] | select((.os[] | . == \"sunos\") and (.architecture[] | . == \"sparc\") and (.class == \"archive\")) | .name"
".files[] | select((.os[] | . == \"windows\") and (.architecture[] | . == \"i386\") and (.class == \"installer\")) | .name"
".files[] | select(.architecture[] | . == \"x86_64\") | .name"
".files[] | select([.macOSmin] | inside([\"10.10\", \"10.11\", \"10.12\"])) | .name"
diff --git a/Tests/RunCMake/CpsExportImport/CMakeLists.txt b/Tests/RunCMake/CpsExportImport/CMakeLists.txt
new file mode 100644
index 0000000..955802c
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 4.0)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CpsExportImport/RunCMakeTest.cmake b/Tests/RunCMake/CpsExportImport/RunCMakeTest.cmake
new file mode 100644
index 0000000..dff26eb
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/RunCMakeTest.cmake
@@ -0,0 +1,24 @@
+include(RunCMake)
+
+set(RunCMake_TEST_OPTIONS
+ -Wno-dev
+ "-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e"
+ "-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES:STRING=e82e467b-f997-4464-8ace-b00808fff261"
+ )
+
+function(build_project test)
+ set(RunCMake_TEST_NO_CLEAN FALSE)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(${test})
+
+ set(RunCMake_TEST_NO_CLEAN TRUE)
+ run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Release)
+ run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . --config Release)
+endfunction()
+
+build_project(TestLibrary)
+build_project(TestExecutable)
diff --git a/Tests/RunCMake/CpsExportImport/TestExecutable.cmake b/Tests/RunCMake/CpsExportImport/TestExecutable.cmake
new file mode 100644
index 0000000..cced129
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/TestExecutable.cmake
@@ -0,0 +1,12 @@
+project(TestLibrary C)
+
+set(CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}/../install")
+set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/../install")
+
+find_package(libb REQUIRED COMPONENTS libb)
+
+add_executable(app app.c)
+
+target_link_libraries(app PUBLIC libb::libb)
+
+install(TARGETS app DESTINATION bin)
diff --git a/Tests/RunCMake/CpsExportImport/TestLibrary.cmake b/Tests/RunCMake/CpsExportImport/TestLibrary.cmake
new file mode 100644
index 0000000..a984f2b
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/TestLibrary.cmake
@@ -0,0 +1,14 @@
+project(TestLibrary C)
+
+set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/../install")
+
+add_library(liba SHARED liba.c)
+add_library(libb SHARED libb.c)
+
+target_link_libraries(libb PUBLIC liba)
+
+install(TARGETS liba EXPORT liba DESTINATION lib)
+install(PACKAGE_INFO liba DESTINATION cps EXPORT liba)
+
+install(TARGETS libb EXPORT libb DESTINATION lib)
+install(PACKAGE_INFO libb DESTINATION cps EXPORT libb)
diff --git a/Tests/RunCMake/CpsExportImport/app.c b/Tests/RunCMake/CpsExportImport/app.c
new file mode 100644
index 0000000..9ad7829
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/app.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+int ask(void);
+
+int main(void)
+{
+ printf("%i\n", ask());
+ return 0;
+}
diff --git a/Tests/RunCMake/CpsExportImport/liba.c b/Tests/RunCMake/CpsExportImport/liba.c
new file mode 100644
index 0000000..a2e2267
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/liba.c
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int answer(void)
+{
+ return 42;
+}
diff --git a/Tests/RunCMake/CpsExportImport/libb.c b/Tests/RunCMake/CpsExportImport/libb.c
new file mode 100644
index 0000000..8ba04af
--- /dev/null
+++ b/Tests/RunCMake/CpsExportImport/libb.c
@@ -0,0 +1,13 @@
+extern
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+int answer(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int ask(void)
+{
+ return answer();
+}
diff --git a/Tests/RunCMake/Instrumentation/check-data-dir.cmake b/Tests/RunCMake/Instrumentation/check-data-dir.cmake
index f2e8235..a20d2cd 100644
--- a/Tests/RunCMake/Instrumentation/check-data-dir.cmake
+++ b/Tests/RunCMake/Instrumentation/check-data-dir.cmake
@@ -107,6 +107,15 @@
snippet_error(${snippet} "Unexpected config: ${config}")
endif()
endif()
+
+ # Verify command args were passed
+ if (filename MATCHES "^cmakeBuild|^ctest")
+ string(JSON command GET "${contents}" command)
+ if (NOT command MATCHES "-.* Debug")
+ snippet_error(${snippet} "Command value missing passed arguments")
+ endif()
+ endif()
+
endforeach()
# Verify that listed snippets match expected roles
diff --git a/Tests/RunCMake/Instrumentation/verify-snippet.cmake b/Tests/RunCMake/Instrumentation/verify-snippet.cmake
index ec997e3..33f9414 100644
--- a/Tests/RunCMake/Instrumentation/verify-snippet.cmake
+++ b/Tests/RunCMake/Instrumentation/verify-snippet.cmake
@@ -49,7 +49,6 @@
has_key("${snippet}" "${contents}" language)
has_key("${snippet}" "${contents}" config)
elseif (filename MATCHES "^custom-*")
- has_key("${snippet}" "${contents}" target)
has_key("${snippet}" "${contents}" outputs)
has_key("${snippet}" "${contents}" outputSizes)
elseif (filename MATCHES "^test-*")
diff --git a/Tests/RunCMake/PackageInfo/Requirements-check.cmake b/Tests/RunCMake/PackageInfo/Requirements-check.cmake
index 59a212f..a082355 100644
--- a/Tests/RunCMake/PackageInfo/Requirements-check.cmake
+++ b/Tests/RunCMake/PackageInfo/Requirements-check.cmake
@@ -8,8 +8,10 @@
file(READ "${out_dir}/bar.cps" content)
expect_value("${content}" "bar" "name")
-expect_null("${content}" "requires" "foo")
-expect_null("${content}" "requires" "test")
+expect_array("${content}" 1 "requires" "foo" "components")
+expect_value("${content}" "libb" "requires" "foo" "components" 0)
+expect_array("${content}" 1 "requires" "test" "components")
+expect_value("${content}" "liba" "requires" "test" "components" 0)
expect_value("${content}" "interface" "components" "libc" "type")
expect_value("${content}" "interface" "components" "libd" "type")
diff --git a/Tests/RunCMake/ctest_instrumentation/CMakeLists.txt.in b/Tests/RunCMake/ctest_instrumentation/CMakeLists.txt.in
new file mode 100644
index 0000000..057f708
--- /dev/null
+++ b/Tests/RunCMake/ctest_instrumentation/CMakeLists.txt.in
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.10)
+@CASE_CMAKELISTS_PREFIX_CODE@
+project(CTestInstrumentation@CASE_NAME@)
+if(USE_INSTRUMENTATION)
+ set(CMAKE_EXPERIMENTAL_INSTRUMENTATION "a37d1069-1972-4901-b9c9-f194aaf2b6e0")
+endif()
+include(CTest)
+add_executable(main main.c)
+add_test(NAME main COMMAND main)
+@CASE_CMAKELISTS_SUFFIX_CODE@
diff --git a/Tests/RunCMake/ctest_instrumentation/InstrumentationInCTestXML-check.cmake b/Tests/RunCMake/ctest_instrumentation/InstrumentationInCTestXML-check.cmake
new file mode 100644
index 0000000..643515b
--- /dev/null
+++ b/Tests/RunCMake/ctest_instrumentation/InstrumentationInCTestXML-check.cmake
@@ -0,0 +1,41 @@
+foreach(xml_type Configure Build Test)
+ file(GLOB xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${xml_type}.xml")
+ if(xml_file)
+ file(READ "${xml_file}" xml_content)
+ if(NOT xml_content MATCHES "AfterHostMemoryUsed")
+ set(RunCMake_TEST_FAILED "'AfterHostMemoryUsed' not found in ${xml_type}.xml")
+ endif()
+ if(NOT xml_type STREQUAL "Test")
+ if(NOT xml_content MATCHES "<Commands>")
+ set(RunCMake_TEST_FAILED "<Commands> element not found in ${xml_type}.xml")
+ endif()
+ endif()
+ if (xml_type STREQUAL "Build")
+ if(NOT xml_content MATCHES "<Targets>")
+ set(RunCMake_TEST_FAILED "<Targets> element not found in Build.xml")
+ endif()
+ if(NOT xml_content MATCHES "<Target name=\"main\" type=\"EXECUTABLE\">")
+ set(RunCMake_TEST_FAILED "<Target> element for 'main' not found in Build.xml")
+ endif()
+ if(NOT xml_content MATCHES "<Compile")
+ set(RunCMake_TEST_FAILED "<Compile> element not found in Build.xml")
+ endif()
+ if(NOT xml_content MATCHES "<Link")
+ set(RunCMake_TEST_FAILED "<Link> element not found in Build.xml")
+ endif()
+ if(NOT xml_content MATCHES "<CmakeBuild")
+ set(RunCMake_TEST_FAILED "<CmakeBuild> element not found in Build.xml")
+ endif()
+ endif()
+ else()
+ set(RunCMake_TEST_FAILED "${xml_type}.xml not found")
+ endif()
+endforeach()
+
+foreach(dir_to_check "configure" "test" "build/targets" "build/commands")
+ file(GLOB leftover_cdash_snippets
+ "${RunCMake_TEST_BINARY_DIR}/.cmake/instrumentation-a37d1069-1972-4901-b9c9-f194aaf2b6e0/v1/cdash/${dir_to_check}/*")
+ if(leftover_cdash_snippets)
+ set(RunCMake_TEST_FAILED "Leftover snippets found in cdash dir: ${leftover_cdash_snippets}")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/ctest_instrumentation/NoInstrumentationInCTestXML-check.cmake b/Tests/RunCMake/ctest_instrumentation/NoInstrumentationInCTestXML-check.cmake
new file mode 100644
index 0000000..f026f76
--- /dev/null
+++ b/Tests/RunCMake/ctest_instrumentation/NoInstrumentationInCTestXML-check.cmake
@@ -0,0 +1,11 @@
+foreach(xml_type Configure Build Test)
+ file(GLOB xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${xml_type}.xml")
+ if(xml_file)
+ file(READ "${xml_file}" xml_content)
+ if(xml_content MATCHES "AfterHostMemoryUsed")
+ set(RunCMake_TEST_FAILED "'AfterHostMemoryUsed' found in ${xml_type}.xml")
+ endif()
+ else()
+ set(RunCMake_TEST_FAILED "${xml_type}.xml not found")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/ctest_instrumentation/RunCMakeTest.cmake b/Tests/RunCMake/ctest_instrumentation/RunCMakeTest.cmake
new file mode 100644
index 0000000..7424b17
--- /dev/null
+++ b/Tests/RunCMake/ctest_instrumentation/RunCMakeTest.cmake
@@ -0,0 +1,22 @@
+include(RunCTest)
+
+function(run_InstrumentationInCTestXML USE_INSTRUMENTATION)
+ if(USE_INSTRUMENTATION)
+ set(ENV{CTEST_USE_INSTRUMENTATION} "1")
+ set(ENV{CTEST_EXPERIMENTAL_INSTRUMENTATION} "a37d1069-1972-4901-b9c9-f194aaf2b6e0")
+ set(RunCMake_USE_INSTRUMENTATION TRUE)
+ set(CASE_NAME InstrumentationInCTestXML)
+ else()
+ set(ENV{CTEST_USE_INSTRUMENTATION} "0")
+ set(ENV{CTEST_EXPERIMENTAL_INSTRUMENTATION} "0")
+ set(RunCMake_USE_INSTRUMENTATION FALSE)
+ set(CASE_NAME NoInstrumentationInCTestXML)
+ endif()
+ configure_file(${RunCMake_SOURCE_DIR}/main.c
+ ${RunCMake_BINARY_DIR}/${CASE_NAME}/main.c COPYONLY)
+ run_ctest("${CASE_NAME}")
+ unset(RunCMake_USE_LAUNCHERS)
+ unset(RunCMake_USE_INSTRUMENTATION)
+endfunction()
+run_InstrumentationInCTestXML(ON)
+run_InstrumentationInCTestXML(OFF)
diff --git a/Tests/RunCMake/ctest_instrumentation/main.c b/Tests/RunCMake/ctest_instrumentation/main.c
new file mode 100644
index 0000000..8488f4e
--- /dev/null
+++ b/Tests/RunCMake/ctest_instrumentation/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/ctest_instrumentation/test.cmake.in b/Tests/RunCMake/ctest_instrumentation/test.cmake.in
new file mode 100644
index 0000000..41b9612
--- /dev/null
+++ b/Tests/RunCMake/ctest_instrumentation/test.cmake.in
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.10)
+
+set(CTEST_SITE "test-site")
+set(CTEST_BUILD_NAME "test-build-name")
+set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@")
+set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build")
+set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@")
+set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
+set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
+set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+set(CTEST_USE_LAUNCHERS TRUE)
+set(CTEST_USE_INSTRUMENTATION "@RunCMake_USE_INSTRUMENTATION@")
+
+ctest_start(Experimental)
+ctest_configure(OPTIONS "-DUSE_INSTRUMENTATION=${CTEST_USE_INSTRUMENTATION}")
+ctest_build()
+ctest_test()
diff --git a/Tests/RunCMake/find_package/CMP0188-NEW-stderr.txt b/Tests/RunCMake/find_package/CMP0188-NEW-stderr.txt
new file mode 100644
index 0000000..bf62647
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0188-NEW-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Warning at CMP0188-NEW\.cmake:[0-9]+ \(find_package\):
+ No "FindGCCXML\.cmake" found in CMAKE_MODULE_PATH\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_package/CMP0188-NEW.cmake b/Tests/RunCMake/find_package/CMP0188-NEW.cmake
new file mode 100644
index 0000000..940169d
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0188-NEW.cmake
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0188 NEW)
+set(_FindGCCXML_testing TRUE)
+find_package(GCCXML MODULE)
+
+if(_FindGCCXML_included)
+ message(FATAL_ERROR "FindGCCXML.cmake erroneously included")
+endif()
diff --git a/Tests/RunCMake/find_package/CMP0188-OLD.cmake b/Tests/RunCMake/find_package/CMP0188-OLD.cmake
new file mode 100644
index 0000000..dc48c43
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0188-OLD.cmake
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0188 OLD)
+set(_FindGCCXML_testing TRUE)
+find_package(GCCXML MODULE)
+
+if(NOT _FindGCCXML_included)
+ message(FATAL_ERROR "FindGCCXML.cmake not included")
+endif()
diff --git a/Tests/RunCMake/find_package/CMP0188-WARN-stderr.txt b/Tests/RunCMake/find_package/CMP0188-WARN-stderr.txt
new file mode 100644
index 0000000..de3b9f8
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0188-WARN-stderr.txt
@@ -0,0 +1,8 @@
+CMake Warning \(dev\) at CMP0188-WARN\.cmake:[0-9]+ \(find_package\):
+ Policy CMP0188 is not set: The FindGCCXML module is removed\. Run "cmake
+ --help-policy CMP0188" for policy details\. Use the cmake_policy command to
+ set the policy and suppress this warning\.
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/find_package/CMP0188-WARN.cmake b/Tests/RunCMake/find_package/CMP0188-WARN.cmake
new file mode 100644
index 0000000..5931da5
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0188-WARN.cmake
@@ -0,0 +1,6 @@
+set(_FindGCCXML_testing TRUE)
+find_package(GCCXML MODULE)
+
+if(NOT _FindGCCXML_included)
+ message(FATAL_ERROR "FindGCCXML.cmake not included")
+endif()
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index 0552535..76a0d10 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -57,6 +57,9 @@
run_cmake(CMP0167-OLD)
run_cmake(CMP0167-WARN)
run_cmake(CMP0167-NEW)
+run_cmake(CMP0188-OLD)
+run_cmake(CMP0188-WARN)
+run_cmake(CMP0188-NEW)
run_cmake(WrongVersionRange)
run_cmake(EmptyVersionRange)
run_cmake(VersionRangeWithEXACT)
diff --git a/Tests/RunCMake/include/CMP0188-NEW-name-result.txt b/Tests/RunCMake/include/CMP0188-NEW-name-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-NEW-name-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include/CMP0188-NEW-name-stderr.txt b/Tests/RunCMake/include/CMP0188-NEW-name-stderr.txt
new file mode 100644
index 0000000..0a86d22
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-NEW-name-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at CMP0188-NEW-name\.cmake:[0-9]+ \(include\):
+ include could not find requested file:
+
+ FindGCCXML
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/include/CMP0188-NEW-name.cmake b/Tests/RunCMake/include/CMP0188-NEW-name.cmake
new file mode 100644
index 0000000..3cce95c
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-NEW-name.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0188 NEW)
+include(FindGCCXML)
diff --git a/Tests/RunCMake/include/CMP0188-NEW-path-result.txt b/Tests/RunCMake/include/CMP0188-NEW-path-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-NEW-path-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include/CMP0188-NEW-path-stderr.txt b/Tests/RunCMake/include/CMP0188-NEW-path-stderr.txt
new file mode 100644
index 0000000..f030d7c
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-NEW-path-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/Modules/FindGCCXML.cmake:[0-9]+ \(message\):
+ The FindGCCXML module has been removed by policy CMP0188\.
+Call Stack \(most recent call first\):
+ CMP0188-NEW-path\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/include/CMP0188-NEW-path.cmake b/Tests/RunCMake/include/CMP0188-NEW-path.cmake
new file mode 100644
index 0000000..efc195a
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-NEW-path.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0188 NEW)
+include(${CMAKE_ROOT}/Modules/FindGCCXML.cmake)
diff --git a/Tests/RunCMake/include/CMP0188-OLD.cmake b/Tests/RunCMake/include/CMP0188-OLD.cmake
new file mode 100644
index 0000000..34d5ad4
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-OLD.cmake
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0188 OLD)
+set(_FindGCCXML_testing 1)
+include(FindGCCXML)
+
+if(NOT _FindGCCXML_included)
+ message(FATAL_ERROR "FindGCCXML.cmake not included")
+endif()
diff --git a/Tests/RunCMake/include/CMP0188-WARN-stderr.txt b/Tests/RunCMake/include/CMP0188-WARN-stderr.txt
new file mode 100644
index 0000000..c07bb89
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-WARN-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Warning \(dev\) at CMP0188-WARN\.cmake:[0-9]+ \(include\):
+ Policy CMP0188 is not set: The FindGCCXML module is removed\. Run "cmake
+ --help-policy CMP0188" for policy details\. Use the cmake_policy command to
+ set the policy and suppress this warning\.
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/include/CMP0188-WARN.cmake b/Tests/RunCMake/include/CMP0188-WARN.cmake
new file mode 100644
index 0000000..99d3557
--- /dev/null
+++ b/Tests/RunCMake/include/CMP0188-WARN.cmake
@@ -0,0 +1,7 @@
+# Do not set CMP0188.
+set(_FindGCCXML_testing 1)
+include(FindGCCXML)
+
+if(NOT _FindGCCXML_included)
+ message(FATAL_ERROR "FindGCCXML.cmake not included")
+endif()
diff --git a/Tests/RunCMake/include/RunCMakeTest.cmake b/Tests/RunCMake/include/RunCMakeTest.cmake
index 68a08bb..994f2a5 100644
--- a/Tests/RunCMake/include/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include/RunCMakeTest.cmake
@@ -25,3 +25,8 @@
run_cmake(CMP0167-WARN)
run_cmake(CMP0167-NEW-name)
run_cmake(CMP0167-NEW-path)
+
+run_cmake(CMP0188-OLD)
+run_cmake(CMP0188-WARN)
+run_cmake(CMP0188-NEW-name)
+run_cmake(CMP0188-NEW-path)
diff --git a/Tests/RunCMake/string/RegexEmptyMatch.cmake b/Tests/RunCMake/string/RegexEmptyMatch.cmake
new file mode 100644
index 0000000..1510137
--- /dev/null
+++ b/Tests/RunCMake/string/RegexEmptyMatch.cmake
@@ -0,0 +1,143 @@
+cmake_policy(SET CMP0186 NEW)
+
+function(check_output name expected)
+ set(output "${${name}}")
+ if(NOT output STREQUAL expected)
+ message(FATAL_ERROR "\"string(REGEX)\" set ${name} to \"${output}\", expected \"${expected}\"")
+ endif()
+endfunction()
+
+# Zero-length matches in REGEX MATCH
+
+string(REGEX MATCH "" out "")
+check_output(out "")
+
+string(REGEX MATCH "" out "a")
+check_output(out "")
+
+string(REGEX MATCH "a*" out "")
+check_output(out "")
+
+string(REGEX MATCH "a*" out "a")
+check_output(out "a")
+
+string(REGEX MATCH "a*" out "b")
+check_output(out "")
+
+string(REGEX MATCH "a*" out "ba")
+check_output(out "")
+
+# Zero-length matches in REGEX MATCHALL
+
+string(REGEX MATCHALL "" out "")
+check_output(out "")
+
+string(REGEX MATCHALL "" out "ab")
+check_output(out ";;")
+
+string(REGEX MATCHALL "^" out "ab")
+check_output(out "")
+
+string(REGEX MATCHALL "(^|,)" out "a,b")
+check_output(out ";,")
+
+string(REGEX MATCHALL "(,|^)" out "a,b")
+check_output(out ";,")
+
+string(REGEX MATCHALL "(^|)" out "")
+check_output(out "")
+
+string(REGEX MATCHALL "(^|)" out "ab")
+check_output(out ";;")
+
+string(REGEX MATCHALL "a|^" out "ab")
+check_output(out "a")
+
+string(REGEX MATCHALL "$" out "ab")
+check_output(out "")
+
+string(REGEX MATCHALL "($|,)" out "a,b")
+check_output(out ",;")
+
+string(REGEX MATCHALL "(,|$)" out "a,b")
+check_output(out ",;")
+
+string(REGEX MATCHALL "(|$)" out "")
+check_output(out "")
+
+string(REGEX MATCHALL "(|$)" out "ab")
+check_output(out ";;")
+
+string(REGEX MATCHALL "(b|)" out "abc")
+check_output(out ";b;;")
+
+string(REGEX MATCHALL "(|b)" out "abc")
+check_output(out ";;b;;")
+
+string(REGEX MATCHALL "a*" out "aaa")
+check_output(out "aaa;")
+
+string(REGEX MATCHALL "(a)?(b)?" out "")
+check_output(out "")
+
+string(REGEX MATCHALL "(a)?(b)?" out "abba")
+check_output(out "ab;b;a;")
+
+# Zero-length matches in REGEX REPLACE
+
+string(REGEX REPLACE "" "" out "")
+check_output(out "")
+
+string(REGEX REPLACE "" "x" out "")
+check_output(out "x")
+
+string(REGEX REPLACE "" "x" out "ab")
+check_output(out "xaxbx")
+
+string(REGEX REPLACE "^" "x" out "ab")
+check_output(out "xab")
+
+string(REGEX REPLACE "(^|,)" "x" out "a,b")
+check_output(out "xaxb")
+
+string(REGEX REPLACE "(,|^)" "x" out "a,b")
+check_output(out "xaxb")
+
+string(REGEX REPLACE "(^|)" "x" out "")
+check_output(out "x")
+
+string(REGEX REPLACE "(^|)" "x" out "ab")
+check_output(out "xaxbx")
+
+string(REGEX REPLACE "a|^" "x" out "ab")
+check_output(out "xb")
+
+string(REGEX REPLACE "$" "x" out "ab")
+check_output(out "abx")
+
+string(REGEX REPLACE "($|,)" "x" out "a,b")
+check_output(out "axbx")
+
+string(REGEX REPLACE "(,|$)" "x" out "a,b")
+check_output(out "axbx")
+
+string(REGEX REPLACE "(|$)" "x" out "")
+check_output(out "x")
+
+string(REGEX REPLACE "(|$)" "x" out "ab")
+check_output(out "xaxbx")
+
+string(REGEX REPLACE "(b|)" "x" out "abc")
+check_output(out "xaxxcx")
+
+string(REGEX REPLACE "(|b)" "x" out "abc")
+check_output(out "xaxxxcx")
+
+string(REGEX REPLACE "a*" "x" out "aaa")
+check_output(out "xx")
+
+string(REGEX REPLACE "(a)?(b)?" "x" out "")
+check_output(out "x")
+
+string(REGEX REPLACE "(a)?(b)?" "x" out "abba")
+check_output(out "xxxx")
diff --git a/Tests/RunCMake/string/RunCMakeTest.cmake b/Tests/RunCMake/string/RunCMakeTest.cmake
index e352fcb..91a03da 100644
--- a/Tests/RunCMake/string/RunCMakeTest.cmake
+++ b/Tests/RunCMake/string/RunCMakeTest.cmake
@@ -35,6 +35,7 @@
run_cmake(RegexClear)
run_cmake(RegexMultiMatchClear)
+run_cmake(RegexEmptyMatch)
run_cmake(CMP0186)
run_cmake(UTF-16BE)
diff --git a/Utilities/Release/README.rst b/Utilities/Release/README.rst
index d5bbd2b..ac671c0 100644
--- a/Utilities/Release/README.rst
+++ b/Utilities/Release/README.rst
@@ -79,6 +79,12 @@
.. _`kitware/cmake Docker Hub Repository`: https://hub.docker.com/r/kitware/cmake
+SunOS
+-----
+
+The ``sunos/`` directory contains infrastructure to cross-compile
+CMake binaries to SunOS from Linux hosts.
+
macOS
-----
diff --git a/Utilities/Release/files-v1.json.in b/Utilities/Release/files-v1.json.in
index 2f860d2..05561c7 100644
--- a/Utilities/Release/files-v1.json.in
+++ b/Utilities/Release/files-v1.json.in
@@ -60,6 +60,30 @@
"macOSmin": "10.10"
},
{
+ "os": ["sunos", "SunOS"],
+ "architecture": ["i386"],
+ "class": "installer",
+ "name": "cmake-@version@-sunos-i386.sh"
+ },
+ {
+ "os": ["sunos", "SunOS"],
+ "architecture": ["i386"],
+ "class": "archive",
+ "name": "cmake-@version@-sunos-i386.tar.gz"
+ },
+ {
+ "os": ["sunos", "SunOS"],
+ "architecture": ["sparc"],
+ "class": "installer",
+ "name": "cmake-@version@-sunos-sparc.sh"
+ },
+ {
+ "os": ["sunos", "SunOS"],
+ "architecture": ["sparc"],
+ "class": "archive",
+ "name": "cmake-@version@-sunos-sparc.tar.gz"
+ },
+ {
"os": ["windows", "Windows"],
"architecture": ["i386"],
"class": "installer",
diff --git a/Utilities/Release/files-v1.rst b/Utilities/Release/files-v1.rst
index f0064e8..b8dbe6f 100644
--- a/Utilities/Release/files-v1.rst
+++ b/Utilities/Release/files-v1.rst
@@ -70,6 +70,9 @@
``Windows``, ``windows``
Windows packages.
+ ``SunOS``, ``sunos``
+ SunOS packages.
+
``architecture``
A JSON array of strings naming the architecture(s) for which the
package file is built, possibly using multiple alternative spellings.
@@ -79,6 +82,7 @@
On Windows, architecture names include ``x86_64``, ``i386``, and ``arm64``.
On macOS, universal binary packages list all architectures,
e.g. ``["arm64","x86_64"]``.
+ On SunOS, architecture names include ``i386`` and ``sparc``.
``class``
A JSON string naming the class of package. The value is one of:
diff --git a/Utilities/Release/sunos/docker/Dockerfile b/Utilities/Release/sunos/docker/Dockerfile
new file mode 100644
index 0000000..626dff4
--- /dev/null
+++ b/Utilities/Release/sunos/docker/Dockerfile
@@ -0,0 +1,53 @@
+# syntax=docker/dockerfile:1
+
+ARG BASE_IMAGE=debian:12
+
+FROM ${BASE_IMAGE} AS apt-cache
+# Populate APT cache w/ the fresh metadata and prefetch packages.
+# Use an empty `docker-clean` file to "hide" the image-provided
+# file to disallow removing packages after `apt-get` operations.
+RUN --mount=type=tmpfs,target=/var/log \
+ --mount=type=bind,source=docker-clean,target=/etc/apt/apt.conf.d/docker-clean \
+ --mount=type=bind,source=base.lst,target=/root/base.lst \
+ --mount=type=bind,source=openssl.lst,target=/root/openssl.lst \
+ apt-get update \
+ && apt-get --download-only -y install $(grep -h '^[^#]\+$' /root/*.lst)
+
+FROM ${BASE_IMAGE} AS base
+ARG ARCH=sparc
+RUN --mount=type=bind,source=base.lst,target=/root/base.lst \
+ --mount=type=bind,source=docker-clean,target=/etc/apt/apt.conf.d/docker-clean \
+ --mount=type=cache,from=apt-cache,source=/var/lib/apt/lists,target=/var/lib/apt/lists \
+ --mount=type=cache,from=apt-cache,source=/var/cache/apt,target=/var/cache/apt,sharing=private \
+ --mount=type=tmpfs,target=/var/log \
+ --mount=type=tmpfs,target=/tmp \
+ apt-get install -y $(grep '^[^#]\+$' /root/base.lst)
+RUN --mount=type=bind,source=base.bash,target=/root/base.bash \
+ --mount=type=tmpfs,target=/tmp \
+ /root/base.bash $ARCH
+
+FROM base AS sysroot
+ARG SYSROOT_URL
+ARG SYSROOT_SHA256SUM
+RUN --mount=type=bind,source=sysroot.bash,target=/root/sysroot.bash \
+ --mount=type=tmpfs,target=/tmp \
+ /root/sysroot.bash $ARCH
+
+FROM sysroot AS openssl
+RUN --mount=type=bind,source=openssl.lst,target=/root/openssl.lst \
+ --mount=type=bind,source=docker-clean,target=/etc/apt/apt.conf.d/docker-clean \
+ --mount=type=cache,from=apt-cache,source=/var/lib/apt/lists,target=/var/lib/apt/lists \
+ --mount=type=cache,from=apt-cache,source=/var/cache/apt,target=/var/cache/apt,sharing=private \
+ --mount=type=tmpfs,target=/var/log \
+ --mount=type=tmpfs,target=/tmp \
+ apt-get install -y $(grep '^[^#]\+$' /root/openssl.lst)
+RUN --mount=type=bind,source=openssl.bash,target=/root/openssl.bash \
+ --mount=type=bind,source=openssl.patch,target=/root/openssl.patch \
+ --mount=type=bind,from=sysroot,source=/opt/cross/sysroot,target=/opt/cross/sysroot \
+ --mount=type=tmpfs,target=/tmp \
+ /root/openssl.bash $ARCH
+
+FROM base
+LABEL maintainer="Brad King <brad.king@kitware.com>"
+RUN --mount=type=bind,from=openssl,source=/root,target=/root \
+ tar xzf /root/openssl.tar.gz -C /
diff --git a/Utilities/Release/sunos/docker/base.bash b/Utilities/Release/sunos/docker/base.bash
new file mode 100755
index 0000000..0c707d0
--- /dev/null
+++ b/Utilities/Release/sunos/docker/base.bash
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+set -e
+
+arch="$1"
+readonly arch
+
+case "$arch" in
+ i386)
+ tarball="gcc-9.5.0-linux-x86_64-cross-sunos-i386.tar.xz"
+ sha256sum="3cd3c989483051e741dd9f39170842d22e5c43cd25628d2b0c57890a3f235883"
+ ;;
+ sparc)
+ tarball="gcc-9.5.0-linux-x86_64-cross-sunos-sparc.tar.xz"
+ sha256sum="853454ef4e787895786fdb21e56a3ba9c121ffe6116467a75f2c3eb09f3c88b4"
+ ;;
+ *)
+ echo >&2 "Unknown architecture: $arch"
+ exit 1
+ ;;
+esac
+readonly tarball
+readonly sha256sum
+
+cd /tmp
+
+curl -OL "https://gitlab.kitware.com/api/v4/projects/6955/packages/generic/gcc-solaris/v9.5.0-20250212.0/$tarball"
+echo "$sha256sum $tarball" > gcc.sha256sum
+sha256sum --check gcc.sha256sum
+
+tar xJf "$tarball" -C /
diff --git a/Utilities/Release/sunos/docker/base.lst b/Utilities/Release/sunos/docker/base.lst
new file mode 100644
index 0000000..6a9a3ec
--- /dev/null
+++ b/Utilities/Release/sunos/docker/base.lst
@@ -0,0 +1,3 @@
+curl
+git
+xz-utils
diff --git a/Utilities/Release/sunos/docker/docker-clean b/Utilities/Release/sunos/docker/docker-clean
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Utilities/Release/sunos/docker/docker-clean
diff --git a/Utilities/Release/sunos/docker/openssl.bash b/Utilities/Release/sunos/docker/openssl.bash
new file mode 100755
index 0000000..86f9ad8
--- /dev/null
+++ b/Utilities/Release/sunos/docker/openssl.bash
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+set -e
+
+arch="$1"
+readonly arch
+
+case "$arch" in
+ i386)
+ target=i386-pc-solaris2.10
+ openssl_target=solaris-x86-gcc
+ ldlibs=
+ ;;
+ sparc)
+ target=sparc-sun-solaris2.10
+ openssl_target=solaris-sparcv8-gcc
+ ldlibs=-latomic
+ ;;
+ *)
+ echo >&2 "Unknown architecture: $arch"
+ exit 1
+ ;;
+esac
+readonly target
+readonly openssl_target
+readonly ldlibs
+
+readonly sha256sum="e15dda82fe2fe8139dc2ac21a36d4ca01d5313c75f99f46c4e8a27709b7294bf"
+readonly filename="openssl-3.4.0"
+readonly tarball="$filename.tar.gz"
+
+cd /tmp
+
+curl -OL "https://github.com/openssl/openssl/releases/download/$filename/$tarball"
+echo "$sha256sum $tarball" > openssl.sha256sum
+sha256sum --check openssl.sha256sum
+
+tar xzf "$tarball"
+
+prefix="/opt/cross/openssl/$target"
+cd "$filename"
+patch -p0 < "${BASH_SOURCE%/*}/openssl.patch"
+env \
+ LDLIBS="$ldlibs" \
+ LDFLAGS="-Wl,-z,noexecstack" \
+ ./Configure \
+ --prefix="$prefix" \
+ --cross-compile-prefix="/opt/cross/bin/$target-" \
+ --api=1.1.1 \
+ "$openssl_target" \
+ no-deprecated \
+ no-shared
+if ! make -j $(nproc) >make.log 2>&1; then
+ tail -1000 make.log
+ exit 1
+fi
+if ! make install_sw >>make.log 2>&1; then
+ tail -1000 make.log
+ exit 1
+fi
+
+tar czf /root/openssl.tar.gz -C / "$prefix"
diff --git a/Utilities/Release/sunos/docker/openssl.lst b/Utilities/Release/sunos/docker/openssl.lst
new file mode 100644
index 0000000..96fd60f
--- /dev/null
+++ b/Utilities/Release/sunos/docker/openssl.lst
@@ -0,0 +1,4 @@
+m4
+make
+patch
+perl
diff --git a/Utilities/Release/sunos/docker/openssl.patch b/Utilities/Release/sunos/docker/openssl.patch
new file mode 100644
index 0000000..98f8362
--- /dev/null
+++ b/Utilities/Release/sunos/docker/openssl.patch
@@ -0,0 +1,22 @@
+--- crypto/sleep.orig
++++ crypto/sleep.c
+@@ -10,6 +10,8 @@
+ #include <openssl/crypto.h>
+ #include "internal/e_os.h"
+
++#define OPENSSL_USE_USLEEP
++
+ /* system-specific variants defining OSSL_sleep() */
+ #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
+
+--- providers/implementations/rands/seeding/rand_unix.c.orig
++++ providers/implementations/rands/seeding/rand_unix.c
+@@ -84,8 +84,6 @@
+ # define OSSL_POSIX_TIMER_OKAY
+ # endif
+ # endif
+-# else
+-# define OSSL_POSIX_TIMER_OKAY
+ # endif
+ # endif
+ #endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
diff --git a/Utilities/Release/sunos/docker/sysroot.bash b/Utilities/Release/sunos/docker/sysroot.bash
new file mode 100755
index 0000000..87ec01e
--- /dev/null
+++ b/Utilities/Release/sunos/docker/sysroot.bash
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+set -e
+
+arch="$1"
+readonly arch
+
+case "$arch" in
+ i386)
+ tarball="sysroot-i386-pc-solaris2.10-sunos5.10-1.tar.xz"
+ sha256sum="1b9251699f4e412ba5b0fde9c0fb96ceef6b8a1f47f0c1f2146ba0ba9da458b8"
+ ;;
+ sparc)
+ tarball="sysroot-sparc-sun-solaris2.10-sunos5.10-1.tar.xz"
+ sha256sum="e6c668a63dc00de443d07cbe2be779335642ffe1b818ba85d23ab543982aaf23"
+ ;;
+ *)
+ echo >&2 "Unknown architecture: $arch"
+ exit 1
+ ;;
+esac
+# To build externally, provide a Solaris sysroot tarball:
+# --build-arg SYSROOT_URL=...
+# --build-arg SYSROOT_SHA256SUM=...
+# The tarball must contain one of:
+# sysroot/i386-pc-solaris2.10/{lib,usr/lib,usr/include}
+# sysroot/sparc-sun-solaris2.10/{lib,usr/lib,usr/include}
+# The content may be retrieved from a real Solaris host.
+if test -n "$SYSROOT_URL"; then
+ url="$SYSROOT_URL"
+ if test -n "$SYSROOT_SHA256SUM"; then
+ sha256sum="$SYSROOT_SHA256SUM"
+ else
+ sha256sum=""
+ fi
+ tarball=$(basename "$url")
+else
+ # This URL is only visible inside of Kitware's network.
+ url="https://cmake.org/files/dependencies/internal/sunos/$tarball"
+fi
+readonly url
+readonly tarball
+readonly sha256sum
+
+cd /tmp
+
+curl -OL "$url"
+if test -n "$sha256sum"; then
+ echo "$sha256sum $tarball" > sysroot.sha256sum
+ sha256sum --check sysroot.sha256sum
+fi
+
+tar xf "$tarball" -C /opt/cross
diff --git a/Utilities/Release/sunos/i386/cache.txt b/Utilities/Release/sunos/i386/cache.txt
new file mode 100644
index 0000000..6bb2c27
--- /dev/null
+++ b/Utilities/Release/sunos/i386/cache.txt
@@ -0,0 +1,25 @@
+CMAKE_BUILD_TYPE:STRING=Release
+
+# Link C++ library statically.
+CMAKE_EXE_LINKER_FLAGS:STRING=-static-libstdc++ -static-libgcc -Wl,-z,noexecstack
+
+# Enable ssl support in curl
+CMAKE_USE_OPENSSL:BOOL=ON
+OPENSSL_USE_STATIC_LIBS:BOOL=ON
+OpenSSL_ROOT:PATH=/opt/cross/openssl/i386-pc-solaris2.10
+
+# Enable ccmake
+BUILD_CursesDialog:BOOL=ON
+
+# Disable cmake-gui
+BUILD_QtDialog:BOOL=OFF
+
+# Disable tests.
+BUILD_TESTING:BOOL=OFF
+CMake_TEST_INSTALL:BOOL=OFF
+
+# Disable unnecessary dependency.
+CMAKE_SKIP_INSTALL_ALL_DEPENDENCY:BOOL=ON
+
+# CPack package file name component for this platform.
+CPACK_SYSTEM_NAME:STRING=sunos-i386
diff --git a/Utilities/Release/sunos/i386/toolchain.cmake b/Utilities/Release/sunos/i386/toolchain.cmake
new file mode 100644
index 0000000..59ce6b5
--- /dev/null
+++ b/Utilities/Release/sunos/i386/toolchain.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_SYSTEM_NAME SunOS)
+set(CMAKE_SYSTEM_VERSION 5.10)
+set(CMAKE_SYSTEM_PROCESSOR i386)
+set(CMAKE_SYSROOT /opt/cross/sysroot/i386-pc-solaris2.10)
+set(CMAKE_C_COMPILER /opt/cross/bin/i386-pc-solaris2.10-gcc)
+set(CMAKE_CXX_COMPILER /opt/cross/bin/i386-pc-solaris2.10-g++)
diff --git a/Utilities/Release/sunos/sparc/cache.txt b/Utilities/Release/sunos/sparc/cache.txt
new file mode 100644
index 0000000..eb12c14
--- /dev/null
+++ b/Utilities/Release/sunos/sparc/cache.txt
@@ -0,0 +1,26 @@
+CMAKE_BUILD_TYPE:STRING=Release
+
+# Link C++ library statically.
+CMAKE_EXE_LINKER_FLAGS:STRING=-static-libstdc++ -static-libgcc -Wl,-z,noexecstack
+
+# Enable ssl support in curl
+CMAKE_USE_OPENSSL:BOOL=ON
+OPENSSL_USE_STATIC_LIBS:BOOL=ON
+OpenSSL_ROOT:PATH=/opt/cross/openssl/sparc-sun-solaris2.10
+_OPENSSL_STATIC_LIBRARIES:STRING=/opt/cross/sparc-sun-solaris2.10/lib/libatomic.a
+
+# Enable ccmake
+BUILD_CursesDialog:BOOL=ON
+
+# Disable cmake-gui
+BUILD_QtDialog:BOOL=OFF
+
+# Disable tests.
+BUILD_TESTING:BOOL=OFF
+CMake_TEST_INSTALL:BOOL=OFF
+
+# Disable unnecessary dependency.
+CMAKE_SKIP_INSTALL_ALL_DEPENDENCY:BOOL=ON
+
+# CPack package file name component for this platform.
+CPACK_SYSTEM_NAME:STRING=sunos-sparc
diff --git a/Utilities/Release/sunos/sparc/toolchain.cmake b/Utilities/Release/sunos/sparc/toolchain.cmake
new file mode 100644
index 0000000..789df8d
--- /dev/null
+++ b/Utilities/Release/sunos/sparc/toolchain.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_SYSTEM_NAME SunOS)
+set(CMAKE_SYSTEM_VERSION 5.10)
+set(CMAKE_SYSTEM_PROCESSOR sparc)
+set(CMAKE_SYSROOT /opt/cross/sysroot/sparc-sun-solaris2.10)
+set(CMAKE_C_COMPILER /opt/cross/bin/sparc-sun-solaris2.10-gcc)
+set(CMAKE_CXX_COMPILER /opt/cross/bin/sparc-sun-solaris2.10-g++)