summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Auxiliary/vim/syntax/cmake.vim3
-rw-r--r--CompileFlags.cmake15
-rw-r--r--Help/command/file.rst1820
-rw-r--r--Help/command/get_filename_component.rst6
-rw-r--r--Help/command/list.rst364
-rw-r--r--Help/command/set.rst161
-rw-r--r--Help/command/string.rst4
-rw-r--r--Help/dev/documentation.rst25
-rw-r--r--Help/envvar/CMAKE_MAXIMUM_RECURSION_DEPTH.rst10
-rw-r--r--Help/manual/cmake-env-variables.7.rst1
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst1
-rw-r--r--Help/manual/cmake-properties.7.rst3
-rw-r--r--Help/prop_tgt/CUDA_CUBIN_COMPILATION.rst14
-rw-r--r--Help/prop_tgt/CUDA_FATBIN_COMPILATION.rst14
-rw-r--r--Help/prop_tgt/CUDA_OPTIX_COMPILATION.rst14
-rw-r--r--Help/release/dev/cuda-support-new-compile-modes.rst14
-rw-r--r--Help/variable/CMAKE_MAXIMUM_RECURSION_DEPTH.rst2
-rw-r--r--Modules/CMakeCUDAInformation.cmake1
-rw-r--r--Modules/CMakeCheckCompilerFlagCommonPatterns.cmake1
-rw-r--r--Modules/CheckCCompilerFlag.cmake1
-rw-r--r--Modules/CheckCXXCompilerFlag.cmake1
-rw-r--r--Modules/CheckFortranCompilerFlag.cmake1
-rw-r--r--Modules/CheckOBJCCompilerFlag.cmake1
-rw-r--r--Modules/CheckOBJCXXCompilerFlag.cmake1
-rw-r--r--Modules/CheckStructHasMember.cmake7
-rw-r--r--Modules/Compiler/IAR-ASM.cmake84
-rw-r--r--Modules/Compiler/IAR.cmake6
-rw-r--r--Modules/Compiler/NVIDIA-CUDA.cmake5
-rw-r--r--Modules/FortranCInterface/CMakeLists.txt10
-rw-r--r--Modules/GenerateExportHeader.cmake18
-rw-r--r--Modules/Internal/CMakeTryCompilerOrLinkerFlag.cmake1
-rw-r--r--Modules/Internal/CheckFlagCommonConfig.cmake10
-rw-r--r--Source/CMakeLists.txt14
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmConfigure.cmake.h.in2
-rw-r--r--Source/cmFindPackageCommand.cxx15
-rw-r--r--Source/cmGeneratorTarget.cxx28
-rw-r--r--Source/cmGlobalGenerator.cxx2
-rw-r--r--Source/cmGlobalGenerator.h2
-rw-r--r--Source/cmMakefile.cxx56
-rw-r--r--Source/cmMakefile.h8
-rw-r--r--Source/cmMakefileTargetGenerator.cxx23
-rw-r--r--Source/cmNinjaTargetGenerator.cxx43
-rw-r--r--Source/cmRST.cxx1
-rw-r--r--Source/cmTarget.cxx43
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx25
-rw-r--r--Tests/CMakeLib/testRST.expect7
-rw-r--r--Tests/CMakeLib/testRST.rst7
-rw-r--r--Tests/CudaOnly/CMakeLists.txt3
-rw-r--r--Tests/CudaOnly/CUBIN/CMakeLists.txt21
-rw-r--r--Tests/CudaOnly/CUBIN/kernelA.cu7
-rw-r--r--Tests/CudaOnly/CUBIN/kernelB.cu7
-rw-r--r--Tests/CudaOnly/CUBIN/kernelC.cu7
-rw-r--r--Tests/CudaOnly/CUBIN/main.cu56
-rw-r--r--Tests/CudaOnly/Fatbin/CMakeLists.txt25
-rw-r--r--Tests/CudaOnly/Fatbin/main.cu56
-rw-r--r--Tests/CudaOnly/OptixIR/CMakeLists.txt33
-rw-r--r--Tests/CudaOnly/OptixIR/main.cu53
-rw-r--r--Tests/EnforceConfig.cmake.in3
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake9
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake9
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/RunCMakeTest.cmake44
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-stderr.txt34
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-default-script-stderr.txt8
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-default-stderr.txt6
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-env-script-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-env-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-stderr.txt7
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-script-stderr.txt8
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-stderr.txt6
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-env-script-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-env-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-invalid-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/function-invalid-env-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-env-script-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-env-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-invalid-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/include-invalid-env-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-env-script-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-env-stderr.txt21
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-stderr.txt5
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-stderr.txt22
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-env-stderr.txt22
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-result.txt1
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-stderr.txt6
-rw-r--r--Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-stderr.txt6
-rw-r--r--Utilities/Sphinx/cmake.py375
-rw-r--r--Utilities/Sphinx/static/cmake.css16
112 files changed, 2486 insertions, 1490 deletions
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index f303bd4..1a47f67 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -128,7 +128,10 @@ syn keyword cmakeProperty contained
\ CPACK_WIX_ACL
\ CROSSCOMPILING_EMULATOR
\ CUDA_ARCHITECTURES
+ \ CUDA_CUBIN_COMPILATION
\ CUDA_EXTENSIONS
+ \ CUDA_FATBIN_COMPILATION
+ \ CUDA_OPTIX_COMPILATION
\ CUDA_PTX_COMPILATION
\ CUDA_RESOLVE_DEVICE_SYMBOLS
\ CUDA_RUNTIME_LIBRARY
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index 6331af1..f94e079 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -8,7 +8,7 @@ if(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Intel")
set(_INTEL_WINDOWS 1)
endif()
-if(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Clang"
+if(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "^(Clang|IntelLLVM)$"
AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
set(_CLANG_MSVC_WINDOWS 1)
endif()
@@ -22,18 +22,19 @@ if(MSVC OR _INTEL_WINDOWS OR _CLANG_MSVC_WINDOWS)
else()
endif()
-if(MSVC)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_CXX_LINKER_WRAPPER_FLAG}-stack:10000000")
-endif()
-
# MSVC 14.28 enables C5105, but the Windows SDK 10.0.18362.0 triggers it.
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 19.28)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -wd5105")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd5105")
endif()
-if(_CLANG_MSVC_WINDOWS AND "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Xlinker -stack:20000000")
+# Use a stack size large enough for CMake_DEFAULT_RECURSION_LIMIT.
+if(MSVC)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " ${CMAKE_CXX_LINKER_WRAPPER_FLAG}-stack:10000000")
+elseif(MINGW OR MSYS OR CYGWIN)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--stack,10000000")
+elseif(_CLANG_MSVC_WINDOWS AND "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -Xlinker -stack:20000000")
endif()
#silence duplicate symbol warnings on AIX
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 6ab7421..25b762c 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -26,7 +26,7 @@ Synopsis
`Reading`_
file(`READ`_ <filename> <out-var> [...])
file(`STRINGS`_ <filename> <out-var> [...])
- file(`\<HASH\> <HASH_>`_ <filename> <out-var>)
+ file(`\<HASH\>`_ <filename> <out-var>)
file(`TIMESTAMP`_ <filename> <out-var> [...])
file(`GET_RUNTIME_DEPENDENCIES`_ [...])
@@ -68,1209 +68,1177 @@ Synopsis
Reading
^^^^^^^
-.. _READ:
-
-.. code-block:: cmake
-
+.. signature::
file(READ <filename> <variable>
[OFFSET <offset>] [LIMIT <max-in>] [HEX])
-Read content from a file called ``<filename>`` and store it in a
-``<variable>``. Optionally start from the given ``<offset>`` and
-read at most ``<max-in>`` bytes. The ``HEX`` option causes data to
-be converted to a hexadecimal representation (useful for binary data). If the
-``HEX`` option is specified, letters in the output (``a`` through ``f``) are in
-lowercase.
-
-.. _STRINGS:
-
-.. code-block:: cmake
+ Read content from a file called ``<filename>`` and store it in a
+ ``<variable>``. Optionally start from the given ``<offset>`` and
+ read at most ``<max-in>`` bytes. The ``HEX`` option causes data to
+ be converted to a hexadecimal representation (useful for binary data).
+ If the ``HEX`` option is specified, letters in the output
+ (``a`` through ``f``) are in lowercase.
+.. signature::
file(STRINGS <filename> <variable> [<options>...])
-Parse a list of ASCII strings from ``<filename>`` and store it in
-``<variable>``. Binary data in the file are ignored. Carriage return
-(``\r``, CR) characters are ignored. The options are:
+ Parse a list of ASCII strings from ``<filename>`` and store it in
+ ``<variable>``. Binary data in the file are ignored. Carriage return
+ (``\r``, CR) characters are ignored. The options are:
-``LENGTH_MAXIMUM <max-len>``
- Consider only strings of at most a given length.
+ ``LENGTH_MAXIMUM <max-len>``
+ Consider only strings of at most a given length.
-``LENGTH_MINIMUM <min-len>``
- Consider only strings of at least a given length.
+ ``LENGTH_MINIMUM <min-len>``
+ Consider only strings of at least a given length.
-``LIMIT_COUNT <max-num>``
- Limit the number of distinct strings to be extracted.
+ ``LIMIT_COUNT <max-num>``
+ Limit the number of distinct strings to be extracted.
-``LIMIT_INPUT <max-in>``
- Limit the number of input bytes to read from the file.
+ ``LIMIT_INPUT <max-in>``
+ Limit the number of input bytes to read from the file.
-``LIMIT_OUTPUT <max-out>``
- Limit the number of total bytes to store in the ``<variable>``.
+ ``LIMIT_OUTPUT <max-out>``
+ Limit the number of total bytes to store in the ``<variable>``.
-``NEWLINE_CONSUME``
- Treat newline characters (``\n``, LF) as part of string content
- instead of terminating at them.
+ ``NEWLINE_CONSUME``
+ Treat newline characters (``\n``, LF) as part of string content
+ instead of terminating at them.
-``NO_HEX_CONVERSION``
- Intel Hex and Motorola S-record files are automatically converted to
- binary while reading unless this option is given.
+ ``NO_HEX_CONVERSION``
+ Intel Hex and Motorola S-record files are automatically converted to
+ binary while reading unless this option is given.
-``REGEX <regex>``
- Consider only strings that match the given regular expression,
- as described under :ref:`string(REGEX) <Regex Specification>`.
+ ``REGEX <regex>``
+ Consider only strings that match the given regular expression,
+ as described under :ref:`string(REGEX) <Regex Specification>`.
-``ENCODING <encoding-type>``
- .. versionadded:: 3.1
+ ``ENCODING <encoding-type>``
+ .. versionadded:: 3.1
- Consider strings of a given encoding. Currently supported encodings are:
- ``UTF-8``, ``UTF-16LE``, ``UTF-16BE``, ``UTF-32LE``, ``UTF-32BE``.
- If the ``ENCODING`` option is not provided and the file has a Byte Order Mark,
- the ``ENCODING`` option will be defaulted to respect the Byte Order Mark.
+ Consider strings of a given encoding. Currently supported encodings are:
+ ``UTF-8``, ``UTF-16LE``, ``UTF-16BE``, ``UTF-32LE``, ``UTF-32BE``.
+ If the ``ENCODING`` option is not provided and the file
+ has a Byte Order Mark, the ``ENCODING`` option will be defaulted
+ to respect the Byte Order Mark.
- .. versionadded:: 3.2
- Added the ``UTF-16LE``, ``UTF-16BE``, ``UTF-32LE``, ``UTF-32BE`` encodings.
+ .. versionadded:: 3.2
+ Added the ``UTF-16LE``, ``UTF-16BE``, ``UTF-32LE``, ``UTF-32BE`` encodings.
-For example, the code
+ For example, the code
-.. code-block:: cmake
+ .. code-block:: cmake
- file(STRINGS myfile.txt myfile)
+ file(STRINGS myfile.txt myfile)
-stores a list in the variable ``myfile`` in which each item is a line
-from the input file.
+ stores a list in the variable ``myfile`` in which each item is a line
+ from the input file.
-.. _HASH:
+.. signature::
+ file(<HASH> <filename> <variable>)
+ :target: <HASH>
-.. code-block:: cmake
+ Compute a cryptographic hash of the content of ``<filename>`` and
+ store it in a ``<variable>``. The supported ``<HASH>`` algorithm names
+ are those listed by the :command:`string(<HASH>)` command.
- file(<HASH> <filename> <variable>)
+.. signature::
+ file(TIMESTAMP <filename> <variable> [<format>] [UTC])
-Compute a cryptographic hash of the content of ``<filename>`` and
-store it in a ``<variable>``. The supported ``<HASH>`` algorithm names
-are those listed by the :ref:`string(\<HASH\>) <Supported Hash Algorithms>`
-command.
+ Compute a string representation of the modification time of ``<filename>``
+ and store it in ``<variable>``. Should the command be unable to obtain a
+ timestamp variable will be set to the empty string ("").
-.. _TIMESTAMP:
+ See the :command:`string(TIMESTAMP)` command for documentation of
+ the ``<format>`` and ``UTC`` options.
-.. code-block:: cmake
+.. signature::
+ file(GET_RUNTIME_DEPENDENCIES [...])
- file(TIMESTAMP <filename> <variable> [<format>] [UTC])
+ .. versionadded:: 3.16
-Compute a string representation of the modification time of ``<filename>``
-and store it in ``<variable>``. Should the command be unable to obtain a
-timestamp variable will be set to the empty string ("").
+ Recursively get the list of libraries depended on by the given files:
-See the :command:`string(TIMESTAMP)` command for documentation of
-the ``<format>`` and ``UTC`` options.
+ .. code-block:: cmake
-.. _GET_RUNTIME_DEPENDENCIES:
+ file(GET_RUNTIME_DEPENDENCIES
+ [RESOLVED_DEPENDENCIES_VAR <deps_var>]
+ [UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>]
+ [CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>]
+ [EXECUTABLES [<executable_files>...]]
+ [LIBRARIES [<library_files>...]]
+ [MODULES [<module_files>...]]
+ [DIRECTORIES [<directories>...]]
+ [BUNDLE_EXECUTABLE <bundle_executable_file>]
+ [PRE_INCLUDE_REGEXES [<regexes>...]]
+ [PRE_EXCLUDE_REGEXES [<regexes>...]]
+ [POST_INCLUDE_REGEXES [<regexes>...]]
+ [POST_EXCLUDE_REGEXES [<regexes>...]]
+ [POST_INCLUDE_FILES [<files>...]]
+ [POST_EXCLUDE_FILES [<files>...]]
+ )
-.. code-block:: cmake
+ Please note that this sub-command is not intended to be used in project mode.
+ It is intended for use at install time, either from code generated by the
+ :command:`install(RUNTIME_DEPENDENCY_SET)` command, or from code provided by
+ the project via :command:`install(CODE)` or :command:`install(SCRIPT)`.
+ For example:
- file(GET_RUNTIME_DEPENDENCIES
- [RESOLVED_DEPENDENCIES_VAR <deps_var>]
- [UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>]
- [CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>]
- [EXECUTABLES [<executable_files>...]]
- [LIBRARIES [<library_files>...]]
- [MODULES [<module_files>...]]
- [DIRECTORIES [<directories>...]]
- [BUNDLE_EXECUTABLE <bundle_executable_file>]
- [PRE_INCLUDE_REGEXES [<regexes>...]]
- [PRE_EXCLUDE_REGEXES [<regexes>...]]
- [POST_INCLUDE_REGEXES [<regexes>...]]
- [POST_EXCLUDE_REGEXES [<regexes>...]]
- [POST_INCLUDE_FILES [<files>...]]
- [POST_EXCLUDE_FILES [<files>...]]
- )
+ .. code-block:: cmake
-.. versionadded:: 3.16
+ install(CODE [[
+ file(GET_RUNTIME_DEPENDENCIES
+ # ...
+ )
+ ]])
+
+ The arguments are as follows:
+
+ ``RESOLVED_DEPENDENCIES_VAR <deps_var>``
+ Name of the variable in which to store the list of resolved dependencies.
+
+ ``UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>``
+ Name of the variable in which to store the list of unresolved
+ dependencies. If this variable is not specified, and there are any
+ unresolved dependencies, an error is issued.
+
+ ``CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>``
+ Variable prefix in which to store conflicting dependency information.
+ Dependencies are conflicting if two files with the same name are found in
+ two different directories. The list of filenames that conflict are stored
+ in ``<conflicting_deps_prefix>_FILENAMES``. For each filename, the list
+ of paths that were found for that filename are stored in
+ ``<conflicting_deps_prefix>_<filename>``.
+
+ ``EXECUTABLES <executable_files>``
+ List of executable files to read for dependencies. These are executables
+ that are typically created with :command:`add_executable`, but they do
+ not have to be created by CMake. On Apple platforms, the paths to these
+ files determine the value of ``@executable_path`` when recursively
+ resolving the libraries. Specifying any kind of library (``STATIC``,
+ ``MODULE``, or ``SHARED``) here will result in undefined behavior.
+
+ ``LIBRARIES <library_files>``
+ List of library files to read for dependencies. These are libraries that
+ are typically created with :command:`add_library(SHARED)`, but they do
+ not have to be created by CMake. Specifying ``STATIC`` libraries,
+ ``MODULE`` libraries, or executables here will result in undefined
+ behavior.
+
+ ``MODULES <module_files>``
+ List of loadable module files to read for dependencies. These are modules
+ that are typically created with :command:`add_library(MODULE)`, but they
+ do not have to be created by CMake. They are typically used by calling
+ ``dlopen()`` at runtime rather than linked at link time with ``ld -l``.
+ Specifying ``STATIC`` libraries, ``SHARED`` libraries, or executables
+ here will result in undefined behavior.
+
+ ``DIRECTORIES <directories>``
+ List of additional directories to search for dependencies. On Linux
+ platforms, these directories are searched if the dependency is not found
+ in any of the other usual paths. If it is found in such a directory, a
+ warning is issued, because it means that the file is incomplete (it does
+ not list all of the directories that contain its dependencies).
+ On Windows platforms, these directories are searched if the dependency
+ is not found in any of the other search paths, but no warning is issued,
+ because searching other paths is a normal part of Windows dependency
+ resolution. On Apple platforms, this argument has no effect.
+
+ ``BUNDLE_EXECUTABLE <bundle_executable_file>``
+ Executable to treat as the "bundle executable" when resolving libraries.
+ On Apple platforms, this argument determines the value of
+ ``@executable_path`` when recursively resolving libraries for
+ ``LIBRARIES`` and ``MODULES`` files. It has no effect on ``EXECUTABLES``
+ files. On other platforms, it has no effect. This is typically (but not
+ always) one of the executables in the ``EXECUTABLES`` argument which
+ designates the "main" executable of the package.
+
+ The following arguments specify filters for including or excluding libraries
+ to be resolved. See below for a full description of how they work.
+
+ ``PRE_INCLUDE_REGEXES <regexes>``
+ List of pre-include regexes through which to filter the names of
+ not-yet-resolved dependencies.
+
+ ``PRE_EXCLUDE_REGEXES <regexes>``
+ List of pre-exclude regexes through which to filter the names of
+ not-yet-resolved dependencies.
+
+ ``POST_INCLUDE_REGEXES <regexes>``
+ List of post-include regexes through which to filter the names of
+ resolved dependencies.
+
+ ``POST_EXCLUDE_REGEXES <regexes>``
+ List of post-exclude regexes through which to filter the names of
+ resolved dependencies.
+
+ ``POST_INCLUDE_FILES <files>``
+ .. versionadded:: 3.21
+
+ List of post-include filenames through which to filter the names of
+ resolved dependencies. Symlinks are resolved when attempting to match
+ these filenames.
+
+ ``POST_EXCLUDE_FILES <files>``
+ .. versionadded:: 3.21
+
+ List of post-exclude filenames through which to filter the names of
+ resolved dependencies. Symlinks are resolved when attempting to match
+ these filenames.
+
+ These arguments can be used to exclude unwanted system libraries when
+ resolving the dependencies, or to include libraries from a specific
+ directory. The filtering works as follows:
+
+ 1. If the not-yet-resolved dependency matches any of the
+ ``PRE_INCLUDE_REGEXES``, steps 2 and 3 are skipped, and the dependency
+ resolution proceeds to step 4.
+
+ 2. If the not-yet-resolved dependency matches any of the
+ ``PRE_EXCLUDE_REGEXES``, dependency resolution stops for that dependency.
+
+ 3. Otherwise, dependency resolution proceeds.
+
+ 4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according
+ to the linking rules of the platform (see below).
+
+ 5. If the dependency is found, and its full path matches one of the
+ ``POST_INCLUDE_REGEXES`` or ``POST_INCLUDE_FILES``, the full path is added
+ to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)``
+ recursively resolves that library's own dependencies. Otherwise, resolution
+ proceeds to step 6.
+
+ 6. If the dependency is found, but its full path matches one of the
+ ``POST_EXCLUDE_REGEXES`` or ``POST_EXCLUDE_FILES``, it is not added to the
+ resolved dependencies, and dependency resolution stops for that dependency.
+
+ 7. If the dependency is found, and its full path does not match either
+ ``POST_INCLUDE_REGEXES``, ``POST_INCLUDE_FILES``, ``POST_EXCLUDE_REGEXES``,
+ or ``POST_EXCLUDE_FILES``, the full path is added to the resolved
+ dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves
+ that library's own dependencies.
+
+ Different platforms have different rules for how dependencies are resolved.
+ These specifics are described here.
+
+ On Linux platforms, library resolution works as follows:
+
+ 1. If the depending file does not have any ``RUNPATH`` entries, and the
+ library exists in one of the depending file's ``RPATH`` entries, or its
+ parents', in that order, the dependency is resolved to that file.
+ 2. Otherwise, if the depending file has any ``RUNPATH`` entries, and the
+ library exists in one of those entries, the dependency is resolved to that
+ file.
+ 3. Otherwise, if the library exists in one of the directories listed by
+ ``ldconfig``, the dependency is resolved to that file.
+ 4. Otherwise, if the library exists in one of the ``DIRECTORIES`` entries,
+ the dependency is resolved to that file. In this case, a warning is
+ issued, because finding a file in one of the ``DIRECTORIES`` means that
+ the depending file is not complete (it does not list all the directories
+ from which it pulls dependencies).
-Recursively get the list of libraries depended on by the given files.
+ 5. Otherwise, the dependency is unresolved.
-Please note that this sub-command is not intended to be used in project mode.
-It is intended for use at install time, either from code generated by the
-:command:`install(RUNTIME_DEPENDENCY_SET)` command, or from code provided by
-the project via :command:`install(CODE)` or :command:`install(SCRIPT)`.
-For example:
+ On Windows platforms, library resolution works as follows:
-.. code-block:: cmake
+ 1. The dependent DLL name is converted to lowercase. Windows DLL names are
+ case-insensitive, and some linkers mangle the case of the DLL dependency
+ names. However, this makes it more difficult for ``PRE_INCLUDE_REGEXES``,
+ ``PRE_EXCLUDE_REGEXES``, ``POST_INCLUDE_REGEXES``, and
+ ``POST_EXCLUDE_REGEXES`` to properly filter DLL names - every regex would
+ have to check for both uppercase and lowercase letters. For example:
- install(CODE [[
- file(GET_RUNTIME_DEPENDENCIES
- # ...
- )
- ]])
-
-The arguments are as follows:
-
-``RESOLVED_DEPENDENCIES_VAR <deps_var>``
- Name of the variable in which to store the list of resolved dependencies.
-
-``UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>``
- Name of the variable in which to store the list of unresolved dependencies.
- If this variable is not specified, and there are any unresolved dependencies,
- an error is issued.
-
-``CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>``
- Variable prefix in which to store conflicting dependency information.
- Dependencies are conflicting if two files with the same name are found in
- two different directories. The list of filenames that conflict are stored in
- ``<conflicting_deps_prefix>_FILENAMES``. For each filename, the list of paths
- that were found for that filename are stored in
- ``<conflicting_deps_prefix>_<filename>``.
-
-``EXECUTABLES <executable_files>``
- List of executable files to read for dependencies. These are executables that
- are typically created with :command:`add_executable`, but they do not have to
- be created by CMake. On Apple platforms, the paths to these files determine
- the value of ``@executable_path`` when recursively resolving the libraries.
- Specifying any kind of library (``STATIC``, ``MODULE``, or ``SHARED``) here
- will result in undefined behavior.
-
-``LIBRARIES <library_files>``
- List of library files to read for dependencies. These are libraries that are
- typically created with :command:`add_library(SHARED)`, but they do not have
- to be created by CMake. Specifying ``STATIC`` libraries, ``MODULE``
- libraries, or executables here will result in undefined behavior.
-
-``MODULES <module_files>``
- List of loadable module files to read for dependencies. These are modules
- that are typically created with :command:`add_library(MODULE)`, but they do
- not have to be created by CMake. They are typically used by calling
- ``dlopen()`` at runtime rather than linked at link time with ``ld -l``.
- Specifying ``STATIC`` libraries, ``SHARED`` libraries, or executables here
- will result in undefined behavior.
-
-``DIRECTORIES <directories>``
- List of additional directories to search for dependencies. On Linux
- platforms, these directories are searched if the dependency is not found in
- any of the other usual paths. If it is found in such a directory, a warning
- is issued, because it means that the file is incomplete (it does not list all
- of the directories that contain its dependencies). On Windows platforms,
- these directories are searched if the dependency is not found in any of the
- other search paths, but no warning is issued, because searching other paths
- is a normal part of Windows dependency resolution. On Apple platforms, this
- argument has no effect.
-
-``BUNDLE_EXECUTABLE <bundle_executable_file>``
- Executable to treat as the "bundle executable" when resolving libraries. On
- Apple platforms, this argument determines the value of ``@executable_path``
- when recursively resolving libraries for ``LIBRARIES`` and ``MODULES`` files.
- It has no effect on ``EXECUTABLES`` files. On other platforms, it has no
- effect. This is typically (but not always) one of the executables in the
- ``EXECUTABLES`` argument which designates the "main" executable of the
- package.
-
-The following arguments specify filters for including or excluding libraries to
-be resolved. See below for a full description of how they work.
-
-``PRE_INCLUDE_REGEXES <regexes>``
- List of pre-include regexes through which to filter the names of
- not-yet-resolved dependencies.
-
-``PRE_EXCLUDE_REGEXES <regexes>``
- List of pre-exclude regexes through which to filter the names of
- not-yet-resolved dependencies.
-
-``POST_INCLUDE_REGEXES <regexes>``
- List of post-include regexes through which to filter the names of resolved
- dependencies.
-
-``POST_EXCLUDE_REGEXES <regexes>``
- List of post-exclude regexes through which to filter the names of resolved
- dependencies.
-
-``POST_INCLUDE_FILES <files>``
- .. versionadded:: 3.21
+ .. code-block:: cmake
- List of post-include filenames through which to filter the names of resolved
- dependencies. Symlinks are resolved when attempting to match these filenames.
+ file(GET_RUNTIME_DEPENDENCIES
+ # ...
+ PRE_INCLUDE_REGEXES "^[Mm][Yy][Ll][Ii][Bb][Rr][Aa][Rr][Yy]\\.[Dd][Ll][Ll]$"
+ )
-``POST_EXCLUDE_FILES <files>``
- .. versionadded:: 3.21
+ Converting the DLL name to lowercase allows the regexes to only match
+ lowercase names, thus simplifying the regex. For example:
- List of post-exclude filenames through which to filter the names of resolved
- dependencies. Symlinks are resolved when attempting to match these filenames.
-
-These arguments can be used to exclude unwanted system libraries when
-resolving the dependencies, or to include libraries from a specific
-directory. The filtering works as follows:
-
-1. If the not-yet-resolved dependency matches any of the
- ``PRE_INCLUDE_REGEXES``, steps 2 and 3 are skipped, and the dependency
- resolution proceeds to step 4.
-2. If the not-yet-resolved dependency matches any of the
- ``PRE_EXCLUDE_REGEXES``, dependency resolution stops for that dependency.
-3. Otherwise, dependency resolution proceeds.
-4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according to
- the linking rules of the platform (see below).
-5. If the dependency is found, and its full path matches one of the
- ``POST_INCLUDE_REGEXES`` or ``POST_INCLUDE_FILES``, the full path is added
- to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)``
- recursively resolves that library's own dependencies. Otherwise, resolution
- proceeds to step 6.
-6. If the dependency is found, but its full path matches one of the
- ``POST_EXCLUDE_REGEXES`` or ``POST_EXCLUDE_FILES``, it is not added to the
- resolved dependencies, and dependency resolution stops for that dependency.
-7. If the dependency is found, and its full path does not match either
- ``POST_INCLUDE_REGEXES``, ``POST_INCLUDE_FILES``, ``POST_EXCLUDE_REGEXES``,
- or ``POST_EXCLUDE_FILES``, the full path is added to the resolved
- dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves
- that library's own dependencies.
-
-Different platforms have different rules for how dependencies are resolved.
-These specifics are described here.
-
-On Linux platforms, library resolution works as follows:
-
-1. If the depending file does not have any ``RUNPATH`` entries, and the library
- exists in one of the depending file's ``RPATH`` entries, or its parents', in
- that order, the dependency is resolved to that file.
-2. Otherwise, if the depending file has any ``RUNPATH`` entries, and the
- library exists in one of those entries, the dependency is resolved to that
- file.
-3. Otherwise, if the library exists in one of the directories listed by
- ``ldconfig``, the dependency is resolved to that file.
-4. Otherwise, if the library exists in one of the ``DIRECTORIES`` entries, the
- dependency is resolved to that file. In this case, a warning is issued,
- because finding a file in one of the ``DIRECTORIES`` means that the
- depending file is not complete (it does not list all the directories from
- which it pulls dependencies).
-5. Otherwise, the dependency is unresolved.
-
-On Windows platforms, library resolution works as follows:
-
-1. The dependent DLL name is converted to lowercase. Windows DLL names are
- case-insensitive, and some linkers mangle the case of the DLL dependency
- names. However, this makes it more difficult for ``PRE_INCLUDE_REGEXES``,
- ``PRE_EXCLUDE_REGEXES``, ``POST_INCLUDE_REGEXES``, and
- ``POST_EXCLUDE_REGEXES`` to properly filter DLL names - every regex would
- have to check for both uppercase and lowercase letters. For example:
-
- .. code-block:: cmake
-
- file(GET_RUNTIME_DEPENDENCIES
- # ...
- PRE_INCLUDE_REGEXES "^[Mm][Yy][Ll][Ii][Bb][Rr][Aa][Rr][Yy]\\.[Dd][Ll][Ll]$"
- )
-
- Converting the DLL name to lowercase allows the regexes to only match
- lowercase names, thus simplifying the regex. For example:
-
- .. code-block:: cmake
-
- file(GET_RUNTIME_DEPENDENCIES
- # ...
- PRE_INCLUDE_REGEXES "^mylibrary\\.dll$"
- )
-
- This regex will match ``mylibrary.dll`` regardless of how it is cased,
- either on disk or in the depending file. (For example, it will match
- ``mylibrary.dll``, ``MyLibrary.dll``, and ``MYLIBRARY.DLL``.)
-
- Please note that the directory portion of any resolved DLLs retains its
- casing and is not converted to lowercase. Only the filename portion is
- converted.
-
-2. (**Not yet implemented**) If the depending file is a Windows Store app, and
- the dependency is listed as a dependency in the application's package
- manifest, the dependency is resolved to that file.
-3. Otherwise, if the library exists in the same directory as the depending
- file, the dependency is resolved to that file.
-4. Otherwise, if the library exists in either the operating system's
- ``system32`` directory or the ``Windows`` directory, in that order, the
- dependency is resolved to that file.
-5. Otherwise, if the library exists in one of the directories specified by
- ``DIRECTORIES``, in the order they are listed, the dependency is resolved to
- that file. In this case, a warning is not issued, because searching other
- directories is a normal part of Windows library resolution.
-6. Otherwise, the dependency is unresolved.
-
-On Apple platforms, library resolution works as follows:
-
-1. If the dependency starts with ``@executable_path/``, and an ``EXECUTABLES``
- argument is in the process of being resolved, and replacing
- ``@executable_path/`` with the directory of the executable yields an
- existing file, the dependency is resolved to that file.
-2. Otherwise, if the dependency starts with ``@executable_path/``, and there is
- a ``BUNDLE_EXECUTABLE`` argument, and replacing ``@executable_path/`` with
- the directory of the bundle executable yields an existing file, the
- dependency is resolved to that file.
-3. Otherwise, if the dependency starts with ``@loader_path/``, and replacing
- ``@loader_path/`` with the directory of the depending file yields an
- existing file, the dependency is resolved to that file.
-4. Otherwise, if the dependency starts with ``@rpath/``, and replacing
- ``@rpath/`` with one of the ``RPATH`` entries of the depending file yields
- an existing file, the dependency is resolved to that file. Note that
- ``RPATH`` entries that start with ``@executable_path/`` or ``@loader_path/``
- also have these items replaced with the appropriate path.
-5. Otherwise, if the dependency is an absolute file that exists, the dependency
- is resolved to that file.
-6. Otherwise, the dependency is unresolved.
-
-This function accepts several variables that determine which tool is used for
-dependency resolution:
-
-.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
-
- Determines which operating system and executable format the files are built
- for. This could be one of several values:
-
- * ``linux+elf``
- * ``windows+pe``
- * ``macos+macho``
-
- If this variable is not specified, it is determined automatically by system
- introspection.
-
-.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
-
- Determines the tool to use for dependency resolution. It could be one of
- several values, depending on the value of
- :variable:`CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`:
-
- ================================================= =============================================
- ``CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`` ``CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL``
- ================================================= =============================================
- ``linux+elf`` ``objdump``
- ``windows+pe`` ``dumpbin``
- ``windows+pe`` ``objdump``
- ``macos+macho`` ``otool``
- ================================================= =============================================
-
- If this variable is not specified, it is determined automatically by system
- introspection.
-
-.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
-
- Determines the path to the tool to use for dependency resolution. This is the
- actual path to ``objdump``, ``dumpbin``, or ``otool``.
-
- If this variable is not specified, it is determined by the value of
- ``CMAKE_OBJDUMP`` if set, else by system introspection.
+ .. code-block:: cmake
- .. versionadded:: 3.18
- Use ``CMAKE_OBJDUMP`` if set.
+ file(GET_RUNTIME_DEPENDENCIES
+ # ...
+ PRE_INCLUDE_REGEXES "^mylibrary\\.dll$"
+ )
-Writing
-^^^^^^^
+ This regex will match ``mylibrary.dll`` regardless of how it is cased,
+ either on disk or in the depending file. (For example, it will match
+ ``mylibrary.dll``, ``MyLibrary.dll``, and ``MYLIBRARY.DLL``.)
-.. _WRITE:
-.. _APPEND:
+ Please note that the directory portion of any resolved DLLs retains its
+ casing and is not converted to lowercase. Only the filename portion is
+ converted.
-.. code-block:: cmake
+ 2. (**Not yet implemented**) If the depending file is a Windows Store app,
+ and the dependency is listed as a dependency in the application's package
+ manifest, the dependency is resolved to that file.
- file(WRITE <filename> <content>...)
- file(APPEND <filename> <content>...)
+ 3. Otherwise, if the library exists in the same directory as the depending
+ file, the dependency is resolved to that file.
-Write ``<content>`` into a file called ``<filename>``. If the file does
-not exist, it will be created. If the file already exists, ``WRITE``
-mode will overwrite it and ``APPEND`` mode will append to the end.
-Any directories in the path specified by ``<filename>`` that do not
-exist will be created.
+ 4. Otherwise, if the library exists in either the operating system's
+ ``system32`` directory or the ``Windows`` directory, in that order, the
+ dependency is resolved to that file.
-If the file is a build input, use the :command:`configure_file` command
-to update the file only when its content changes.
+ 5. Otherwise, if the library exists in one of the directories specified by
+ ``DIRECTORIES``, in the order they are listed, the dependency is resolved
+ to that file. In this case, a warning is not issued, because searching
+ other directories is a normal part of Windows library resolution.
-.. _TOUCH:
-.. _TOUCH_NOCREATE:
+ 6. Otherwise, the dependency is unresolved.
-.. code-block:: cmake
+ On Apple platforms, library resolution works as follows:
- file(TOUCH [<files>...])
- file(TOUCH_NOCREATE [<files>...])
+ 1. If the dependency starts with ``@executable_path/``, and an
+ ``EXECUTABLES`` argument is in the process of being resolved, and
+ replacing ``@executable_path/`` with the directory of the executable
+ yields an existing file, the dependency is resolved to that file.
-.. versionadded:: 3.12
+ 2. Otherwise, if the dependency starts with ``@executable_path/``, and there
+ is a ``BUNDLE_EXECUTABLE`` argument, and replacing ``@executable_path/``
+ with the directory of the bundle executable yields an existing file, the
+ dependency is resolved to that file.
-Create a file with no content if it does not yet exist. If the file already
-exists, its access and/or modification will be updated to the time when the
-function call is executed.
+ 3. Otherwise, if the dependency starts with ``@loader_path/``, and replacing
+ ``@loader_path/`` with the directory of the depending file yields an
+ existing file, the dependency is resolved to that file.
-Use TOUCH_NOCREATE to touch a file if it exists but not create it. If a file
-does not exist it will be silently ignored.
+ 4. Otherwise, if the dependency starts with ``@rpath/``, and replacing
+ ``@rpath/`` with one of the ``RPATH`` entries of the depending file
+ yields an existing file, the dependency is resolved to that file.
+ Note that ``RPATH`` entries that start with ``@executable_path/`` or
+ ``@loader_path/`` also have these items replaced with the appropriate
+ path.
-With TOUCH and TOUCH_NOCREATE the contents of an existing file will not be
-modified.
+ 5. Otherwise, if the dependency is an absolute file that exists,
+ the dependency is resolved to that file.
-.. _GENERATE:
+ 6. Otherwise, the dependency is unresolved.
-.. code-block:: cmake
+ This function accepts several variables that determine which tool is used for
+ dependency resolution:
- file(GENERATE OUTPUT output-file
- <INPUT input-file|CONTENT content>
- [CONDITION expression] [TARGET target]
- [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
- FILE_PERMISSIONS <permissions>...]
- [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
+ .. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
-Generate an output file for each build configuration supported by the current
-:manual:`CMake Generator <cmake-generators(7)>`. Evaluate
-:manual:`generator expressions <cmake-generator-expressions(7)>`
-from the input content to produce the output content. The options are:
+ Determines which operating system and executable format the files are built
+ for. This could be one of several values:
-``CONDITION <condition>``
- Generate the output file for a particular configuration only if
- the condition is true. The condition must be either ``0`` or ``1``
- after evaluating generator expressions.
+ * ``linux+elf``
+ * ``windows+pe``
+ * ``macos+macho``
-``CONTENT <content>``
- Use the content given explicitly as input.
+ If this variable is not specified, it is determined automatically by system
+ introspection.
-``INPUT <input-file>``
- Use the content from a given file as input.
+ .. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
- .. versionchanged:: 3.10
- A relative path is treated with respect to the value of
- :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
+ Determines the tool to use for dependency resolution. It could be one of
+ several values, depending on the value of
+ :variable:`CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`:
-``OUTPUT <output-file>``
- Specify the output file name to generate. Use generator expressions
- such as :genex:`$<CONFIG>` to specify a configuration-specific
- output file name. Multiple configurations may generate the same output
- file only if the generated content is identical. Otherwise, the
- ``<output-file>`` must evaluate to an unique name for each configuration.
+ ================================================= =============================================
+ ``CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`` ``CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL``
+ ================================================= =============================================
+ ``linux+elf`` ``objdump``
+ ``windows+pe`` ``objdump`` or ``dumpbin``
+ ``macos+macho`` ``otool``
+ ================================================= =============================================
- .. versionchanged:: 3.10
- A relative path (after evaluating generator expressions) is treated
- with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
- See policy :policy:`CMP0070`.
+ If this variable is not specified, it is determined automatically by system
+ introspection.
-``TARGET <target>``
- .. versionadded:: 3.19
+ .. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
- Specify which target to use when evaluating generator expressions that
- require a target for evaluation (e.g.
- :genex:`$<COMPILE_FEATURES:...>`,
- :genex:`$<TARGET_PROPERTY:prop>`).
+ Determines the path to the tool to use for dependency resolution. This is
+ the actual path to ``objdump``, ``dumpbin``, or ``otool``.
-``NO_SOURCE_PERMISSIONS``
- .. versionadded:: 3.20
+ If this variable is not specified, it is determined by the value of
+ ``CMAKE_OBJDUMP`` if set, else by system introspection.
- The generated file permissions default to the standard 644 value
- (-rw-r--r--).
+ .. versionadded:: 3.18
+ Use ``CMAKE_OBJDUMP`` if set.
-``USE_SOURCE_PERMISSIONS``
- .. versionadded:: 3.20
+Writing
+^^^^^^^
- Transfer the file permissions of the ``INPUT`` file to the generated file.
- This is already the default behavior if none of the three permissions-related
- keywords are given (``NO_SOURCE_PERMISSIONS``, ``USE_SOURCE_PERMISSIONS``
- or ``FILE_PERMISSIONS``). The ``USE_SOURCE_PERMISSIONS`` keyword mostly
- serves as a way of making the intended behavior clearer at the call site.
- It is an error to specify this option without ``INPUT``.
+.. signature::
+ file(WRITE <filename> <content>...)
+ file(APPEND <filename> <content>...)
-``FILE_PERMISSIONS <permissions>...``
- .. versionadded:: 3.20
+ Write ``<content>`` into a file called ``<filename>``. If the file does
+ not exist, it will be created. If the file already exists, ``WRITE``
+ mode will overwrite it and ``APPEND`` mode will append to the end.
+ Any directories in the path specified by ``<filename>`` that do not
+ exist will be created.
- Use the specified permissions for the generated file.
+ If the file is a build input, use the :command:`configure_file` command
+ to update the file only when its content changes.
-``NEWLINE_STYLE <style>``
- .. versionadded:: 3.20
+.. signature::
+ file(TOUCH [<files>...])
+ file(TOUCH_NOCREATE [<files>...])
- Specify the newline style for the generated file. Specify
- ``UNIX`` or ``LF`` for ``\n`` newlines, or specify
- ``DOS``, ``WIN32``, or ``CRLF`` for ``\r\n`` newlines.
+ .. versionadded:: 3.12
-Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
-``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
-Generated files are modified and their timestamp updated on subsequent cmake
-runs only if their content is changed.
+ Create a file with no content if it does not yet exist. If the file already
+ exists, its access and/or modification will be updated to the time when the
+ function call is executed.
-Note also that ``file(GENERATE)`` does not create the output file until the
-generation phase. The output file will not yet have been written when the
-``file(GENERATE)`` command returns, it is written only after processing all
-of a project's ``CMakeLists.txt`` files.
+ Use ``TOUCH_NOCREATE`` to touch a file if it exists but not create it.
+ If a file does not exist it will be silently ignored.
-.. _CONFIGURE:
+ With ``TOUCH`` and ``TOUCH_NOCREATE``, the contents of an existing file
+ will not be modified.
-.. code-block:: cmake
+.. signature::
+ file(GENERATE [...])
- file(CONFIGURE OUTPUT output-file
- CONTENT content
- [ESCAPE_QUOTES] [@ONLY]
- [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
+ Generate an output file for each build configuration supported by the current
+ :manual:`CMake Generator <cmake-generators(7)>`. Evaluate
+ :manual:`generator expressions <cmake-generator-expressions(7)>`
+ from the input content to produce the output content.
-.. versionadded:: 3.18
+ .. code-block:: cmake
-Generate an output file using the input given by ``CONTENT`` and substitute
-variable values referenced as ``@VAR@`` or ``${VAR}`` contained therein. The
-substitution rules behave the same as the :command:`configure_file` command.
-In order to match :command:`configure_file`'s behavior, generator expressions
-are not supported for both ``OUTPUT`` and ``CONTENT``.
+ file(GENERATE OUTPUT <output-file>
+ <INPUT <input-file>|CONTENT <content>>
+ [CONDITION <expression>] [TARGET <target>]
+ [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
+ FILE_PERMISSIONS <permissions>...]
+ [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
-The arguments are:
+ The options are:
-``OUTPUT <output-file>``
- Specify the output file name to generate. A relative path is treated with
- respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
- ``<output-file>`` does not support generator expressions.
+ ``CONDITION <condition>``
+ Generate the output file for a particular configuration only if
+ the condition is true. The condition must be either ``0`` or ``1``
+ after evaluating generator expressions.
-``CONTENT <content>``
- Use the content given explicitly as input.
- ``<content>`` does not support generator expressions.
+ ``CONTENT <content>``
+ Use the content given explicitly as input.
-``ESCAPE_QUOTES``
- Escape any substituted quotes with backslashes (C-style).
+ ``INPUT <input-file>``
+ Use the content from a given file as input.
-``@ONLY``
- Restrict variable replacement to references of the form ``@VAR@``.
- This is useful for configuring scripts that use ``${VAR}`` syntax.
+ .. versionchanged:: 3.10
+ A relative path is treated with respect to the value of
+ :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
-``NEWLINE_STYLE <style>``
- Specify the newline style for the output file. Specify
- ``UNIX`` or ``LF`` for ``\n`` newlines, or specify
- ``DOS``, ``WIN32``, or ``CRLF`` for ``\r\n`` newlines.
+ ``OUTPUT <output-file>``
+ Specify the output file name to generate. Use generator expressions
+ such as :genex:`$<CONFIG>` to specify a configuration-specific
+ output file name. Multiple configurations may generate the same output
+ file only if the generated content is identical. Otherwise, the
+ ``<output-file>`` must evaluate to an unique name for each configuration.
-Filesystem
-^^^^^^^^^^
+ .. versionchanged:: 3.10
+ A relative path (after evaluating generator expressions) is treated
+ with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ See policy :policy:`CMP0070`.
-.. _GLOB:
-.. _GLOB_RECURSE:
+ ``TARGET <target>``
+ .. versionadded:: 3.19
-.. code-block:: cmake
+ Specify which target to use when evaluating generator expressions that
+ require a target for evaluation (e.g.
+ :genex:`$<COMPILE_FEATURES:...>`,
+ :genex:`$<TARGET_PROPERTY:prop>`).
- file(GLOB <variable>
- [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
- [<globbing-expressions>...])
- file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
- [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
- [<globbing-expressions>...])
+ ``NO_SOURCE_PERMISSIONS``
+ .. versionadded:: 3.20
-Generate a list of files that match the ``<globbing-expressions>`` and
-store it into the ``<variable>``. Globbing expressions are similar to
-regular expressions, but much simpler. If ``RELATIVE`` flag is
-specified, the results will be returned as relative paths to the given
-path.
+ The generated file permissions default to the standard 644 value
+ (-rw-r--r--).
-.. versionchanged:: 3.6
- The results will be ordered lexicographically.
+ ``USE_SOURCE_PERMISSIONS``
+ .. versionadded:: 3.20
-On Windows and macOS, globbing is case-insensitive even if the underlying
-filesystem is case-sensitive (both filenames and globbing expressions are
-converted to lowercase before matching). On other platforms, globbing is
-case-sensitive.
+ Transfer the file permissions of the ``INPUT`` file to the generated
+ file. This is already the default behavior if none of the three
+ permissions-related keywords are given (``NO_SOURCE_PERMISSIONS``,
+ ``USE_SOURCE_PERMISSIONS`` or ``FILE_PERMISSIONS``). The
+ ``USE_SOURCE_PERMISSIONS`` keyword mostly serves as a way of making
+ the intended behavior clearer at the call site. It is an error to
+ specify this option without ``INPUT``.
-.. versionadded:: 3.3
- By default ``GLOB`` lists directories - directories are omitted in result if
- ``LIST_DIRECTORIES`` is set to false.
+ ``FILE_PERMISSIONS <permissions>...``
+ .. versionadded:: 3.20
-.. versionadded:: 3.12
- If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic
- to the main build system check target to rerun the flagged ``GLOB`` commands
- at build time. If any of the outputs change, CMake will regenerate the build
- system.
+ Use the specified permissions for the generated file.
-.. note::
- We do not recommend using GLOB to collect a list of source files from
- your source tree. If no CMakeLists.txt file changes when a source is
- added or removed then the generated build system cannot know when to
- ask CMake to regenerate.
- The ``CONFIGURE_DEPENDS`` flag may not work reliably on all generators, or if
- a new generator is added in the future that cannot support it, projects using
- it will be stuck. Even if ``CONFIGURE_DEPENDS`` works reliably, there is
- still a cost to perform the check on every rebuild.
+ ``NEWLINE_STYLE <style>``
+ .. versionadded:: 3.20
-Examples of globbing expressions include::
+ Specify the newline style for the generated file. Specify
+ ``UNIX`` or ``LF`` for ``\n`` newlines, or specify
+ ``DOS``, ``WIN32``, or ``CRLF`` for ``\r\n`` newlines.
- *.cxx - match all files with extension cxx
- *.vt? - match all files with extension vta,...,vtz
- f[3-5].txt - match files f3.txt, f4.txt, f5.txt
+ Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
+ ``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
+ Generated files are modified and their timestamp updated on subsequent cmake
+ runs only if their content is changed.
-The ``GLOB_RECURSE`` mode will traverse all the subdirectories of the
-matched directory and match the files. Subdirectories that are symlinks
-are only traversed if ``FOLLOW_SYMLINKS`` is given or policy
-:policy:`CMP0009` is not set to ``NEW``.
+ Note also that ``file(GENERATE)`` does not create the output file until the
+ generation phase. The output file will not yet have been written when the
+ ``file(GENERATE)`` command returns, it is written only after processing all
+ of a project's ``CMakeLists.txt`` files.
-.. versionadded:: 3.3
- By default ``GLOB_RECURSE`` omits directories from result list - setting
- ``LIST_DIRECTORIES`` to true adds directories to result list.
- If ``FOLLOW_SYMLINKS`` is given or policy :policy:`CMP0009` is not set to
- ``NEW`` then ``LIST_DIRECTORIES`` treats symlinks as directories.
+.. signature::
+ file(CONFIGURE OUTPUT <output-file>
+ CONTENT <content>
+ [ESCAPE_QUOTES] [@ONLY]
+ [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
+ :target: CONFIGURE
-Examples of recursive globbing include::
+ .. versionadded:: 3.18
- /dir/*.py - match all python files in /dir and subdirectories
+ Generate an output file using the input given by ``CONTENT`` and substitute
+ variable values referenced as ``@VAR@`` or ``${VAR}`` contained therein. The
+ substitution rules behave the same as the :command:`configure_file` command.
+ In order to match :command:`configure_file`'s behavior, generator expressions
+ are not supported for both ``OUTPUT`` and ``CONTENT``.
-.. _MAKE_DIRECTORY:
+ The arguments are:
-.. code-block:: cmake
+ ``OUTPUT <output-file>``
+ Specify the output file name to generate. A relative path is treated with
+ respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ ``<output-file>`` does not support generator expressions.
- file(MAKE_DIRECTORY [<directories>...])
+ ``CONTENT <content>``
+ Use the content given explicitly as input.
+ ``<content>`` does not support generator expressions.
-Create the given directories and their parents as needed.
+ ``ESCAPE_QUOTES``
+ Escape any substituted quotes with backslashes (C-style).
-.. _REMOVE:
-.. _REMOVE_RECURSE:
+ ``@ONLY``
+ Restrict variable replacement to references of the form ``@VAR@``.
+ This is useful for configuring scripts that use ``${VAR}`` syntax.
-.. code-block:: cmake
+ ``NEWLINE_STYLE <style>``
+ Specify the newline style for the output file. Specify
+ ``UNIX`` or ``LF`` for ``\n`` newlines, or specify
+ ``DOS``, ``WIN32``, or ``CRLF`` for ``\r\n`` newlines.
- file(REMOVE [<files>...])
- file(REMOVE_RECURSE [<files>...])
+Filesystem
+^^^^^^^^^^
-Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given
-files and directories, also non-empty directories. No error is emitted if a
-given file does not exist. Relative input paths are evaluated with respect
-to the current source directory.
+.. signature::
+ file(GLOB <variable>
+ [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
+ [<globbing-expressions>...])
+ file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
+ [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
+ [<globbing-expressions>...])
-.. versionchanged:: 3.15
- Empty input paths are ignored with a warning. Previous versions of CMake
- interpreted empty strings as a relative path with respect to the current
- directory and removed its contents.
+ Generate a list of files that match the ``<globbing-expressions>`` and
+ store it into the ``<variable>``. Globbing expressions are similar to
+ regular expressions, but much simpler. If ``RELATIVE`` flag is
+ specified, the results will be returned as relative paths to the given
+ path.
+
+ .. versionchanged:: 3.6
+ The results will be ordered lexicographically.
+
+ On Windows and macOS, globbing is case-insensitive even if the underlying
+ filesystem is case-sensitive (both filenames and globbing expressions are
+ converted to lowercase before matching). On other platforms, globbing is
+ case-sensitive.
+
+ .. versionadded:: 3.3
+ By default ``GLOB`` lists directories. Directories are omitted in the
+ result if ``LIST_DIRECTORIES`` is set to false.
+
+ .. versionadded:: 3.12
+ If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic
+ to the main build system check target to rerun the flagged ``GLOB``
+ commands at build time. If any of the outputs change, CMake will regenerate
+ the build system.
+
+ .. note::
+ We do not recommend using GLOB to collect a list of source files from
+ your source tree. If no CMakeLists.txt file changes when a source is
+ added or removed then the generated build system cannot know when to
+ ask CMake to regenerate.
+ The ``CONFIGURE_DEPENDS`` flag may not work reliably on all generators, or
+ if a new generator is added in the future that cannot support it, projects
+ using it will be stuck. Even if ``CONFIGURE_DEPENDS`` works reliably, there
+ is still a cost to perform the check on every rebuild.
+
+ Examples of globbing expressions include:
+
+ ============== ======================================================
+ ``*.cxx`` match all files with extension ``cxx``
+ ``*.vt?`` match all files with extension ``vta``, ..., ``vtz``
+ ``f[3-5].txt`` match files ``f3.txt``, ``f4.txt``, ``f5.txt``
+ ============== ======================================================
+
+ The ``GLOB_RECURSE`` mode will traverse all the subdirectories of the
+ matched directory and match the files. Subdirectories that are symlinks
+ are only traversed if ``FOLLOW_SYMLINKS`` is given or policy
+ :policy:`CMP0009` is not set to ``NEW``.
+
+ .. versionadded:: 3.3
+ By default ``GLOB_RECURSE`` omits directories from result list. Setting
+ ``LIST_DIRECTORIES`` to true adds directories to result list.
+ If ``FOLLOW_SYMLINKS`` is given or policy :policy:`CMP0009` is not set to
+ ``NEW`` then ``LIST_DIRECTORIES`` treats symlinks as directories.
+
+ Examples of recursive globbing include:
+
+ ============== ======================================================
+ ``/dir/*.py`` match all python files in ``/dir`` and subdirectories
+ ============== ======================================================
+
+.. signature::
+ file(MAKE_DIRECTORY [<directories>...])
-.. _RENAME:
+ Create the given directories and their parents as needed.
-.. code-block:: cmake
+.. signature::
+ file(REMOVE [<files>...])
+ file(REMOVE_RECURSE [<files>...])
- file(RENAME <oldname> <newname>
- [RESULT <result>]
- [NO_REPLACE])
+ Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given
+ files and directories, including non-empty directories. No error is emitted
+ if a given file does not exist. Relative input paths are evaluated with
+ respect to the current source directory.
-Move a file or directory within a filesystem from ``<oldname>`` to
-``<newname>``, replacing the destination atomically.
+ .. versionchanged:: 3.15
+ Empty input paths are ignored with a warning. Previous versions of CMake
+ interpreted empty strings as a relative path with respect to the current
+ directory and removed its contents.
-The options are:
+.. signature::
+ file(RENAME <oldname> <newname> [RESULT <result>] [NO_REPLACE])
-``RESULT <result>``
- .. versionadded:: 3.21
+ Move a file or directory within a filesystem from ``<oldname>`` to
+ ``<newname>``, replacing the destination atomically.
- Set ``<result>`` variable to ``0`` on success or an error message otherwise.
- If ``RESULT`` is not specified and the operation fails, an error is emitted.
+ The options are:
-``NO_REPLACE``
- .. versionadded:: 3.21
+ ``RESULT <result>``
+ .. versionadded:: 3.21
- If the ``<newname>`` path already exists, do not replace it.
- If ``RESULT <result>`` is used, the result variable will be
- set to ``NO_REPLACE``. Otherwise, an error is emitted.
+ Set ``<result>`` variable to ``0`` on success or an error message
+ otherwise. If ``RESULT`` is not specified and the operation fails,
+ an error is emitted.
-.. _COPY_FILE:
+ ``NO_REPLACE``
+ .. versionadded:: 3.21
-.. code-block:: cmake
+ If the ``<newname>`` path already exists, do not replace it.
+ If ``RESULT <result>`` is used, the result variable will be
+ set to ``NO_REPLACE``. Otherwise, an error is emitted.
+.. signature::
file(COPY_FILE <oldname> <newname>
[RESULT <result>]
[ONLY_IF_DIFFERENT]
[INPUT_MAY_BE_RECENT])
-.. versionadded:: 3.21
-
-Copy a file from ``<oldname>`` to ``<newname>``. Directories are not
-supported. Symlinks are ignored and ``<oldfile>``'s content is read and
-written to ``<newname>`` as a new file.
-
-The options are:
-
-``RESULT <result>``
- Set ``<result>`` variable to ``0`` on success or an error message otherwise.
- If ``RESULT`` is not specified and the operation fails, an error is emitted.
+ .. versionadded:: 3.21
-``ONLY_IF_DIFFERENT``
- If the ``<newname>`` path already exists, do not replace it if the file's
- contents are already the same as ``<oldname>`` (this avoids updating
- ``<newname>``'s timestamp).
+ Copy a file from ``<oldname>`` to ``<newname>``. Directories are not
+ supported. Symlinks are ignored and ``<oldfile>``'s content is read and
+ written to ``<newname>`` as a new file.
-``INPUT_MAY_BE_RECENT``
- .. versionadded:: 3.26
+ The options are:
- Tell CMake that the input file may have been recently created. This is
- meaningful only on Windows, where files may be inaccessible for a short
- time after they are created. With this option, if permission is denied,
- CMake will retry reading the input a few times.
+ ``RESULT <result>``
+ Set ``<result>`` variable to ``0`` on success or an error message
+ otherwise. If ``RESULT`` is not specified and the operation fails,
+ an error is emitted.
-This sub-command has some similarities to :command:`configure_file` with the
-``COPYONLY`` option. An important difference is that :command:`configure_file`
-creates a dependency on the source file, so CMake will be re-run if it changes.
-The ``file(COPY_FILE)`` sub-command does not create such a dependency.
+ ``ONLY_IF_DIFFERENT``
+ If the ``<newname>`` path already exists, do not replace it if the file's
+ contents are already the same as ``<oldname>`` (this avoids updating
+ ``<newname>``'s timestamp).
-See also the ``file(COPY)`` sub-command just below which provides
-further file-copying capabilities.
+ ``INPUT_MAY_BE_RECENT``
+ .. versionadded:: 3.26
-.. _COPY:
-.. _INSTALL:
+ Tell CMake that the input file may have been recently created. This is
+ meaningful only on Windows, where files may be inaccessible for a short
+ time after they are created. With this option, if permission is denied,
+ CMake will retry reading the input a few times.
-.. code-block:: cmake
+ This sub-command has some similarities to :command:`configure_file`
+ with the ``COPYONLY`` option. An important difference is that
+ :command:`configure_file` creates a dependency on the source file,
+ so CMake will be re-run if it changes. The ``file(COPY_FILE)``
+ sub-command does not create such a dependency.
- file(<COPY|INSTALL> <files>... DESTINATION <dir>
- [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS]
- [FILE_PERMISSIONS <permissions>...]
- [DIRECTORY_PERMISSIONS <permissions>...]
- [FOLLOW_SYMLINK_CHAIN]
- [FILES_MATCHING]
- [[PATTERN <pattern> | REGEX <regex>]
- [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
+ See also the :command:`file(COPY)` sub-command just below which provides
+ further file-copying capabilities.
-.. note::
+.. signature::
+ file(COPY [...])
+ file(INSTALL [...])
- For a simple file copying operation, the ``file(COPY_FILE)`` sub-command
- just above may be easier to use.
+ The ``COPY`` signature copies files, directories, and symlinks to a
+ destination folder. Relative input paths are evaluated with respect
+ to the current source directory, and a relative destination is
+ evaluated with respect to the current build directory. Copying
+ preserves input file timestamps, and optimizes out a file if it exists
+ at the destination with the same timestamp. Copying preserves input
+ permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
+ are given (default is ``USE_SOURCE_PERMISSIONS``).
-The ``COPY`` signature copies files, directories, and symlinks to a
-destination folder. Relative input paths are evaluated with respect
-to the current source directory, and a relative destination is
-evaluated with respect to the current build directory. Copying
-preserves input file timestamps, and optimizes out a file if it exists
-at the destination with the same timestamp. Copying preserves input
-permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
-are given (default is ``USE_SOURCE_PERMISSIONS``).
+ .. code-block:: cmake
-.. versionadded:: 3.15
- If ``FOLLOW_SYMLINK_CHAIN`` is specified, ``COPY`` will recursively resolve
- the symlinks at the paths given until a real file is found, and install
- a corresponding symlink in the destination for each symlink encountered. For
- each symlink that is installed, the resolution is stripped of the directory,
- leaving only the filename, meaning that the new symlink points to a file in
- the same directory as the symlink. This feature is useful on some Unix systems,
- where libraries are installed as a chain of symlinks with version numbers, with
- less specific versions pointing to more specific versions.
- ``FOLLOW_SYMLINK_CHAIN`` will install all of these symlinks and the library
- itself into the destination directory. For example, if you have the following
- directory structure:
+ file(<COPY|INSTALL> <files>... DESTINATION <dir>
+ [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS]
+ [FILE_PERMISSIONS <permissions>...]
+ [DIRECTORY_PERMISSIONS <permissions>...]
+ [FOLLOW_SYMLINK_CHAIN]
+ [FILES_MATCHING]
+ [[PATTERN <pattern> | REGEX <regex>]
+ [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
-* ``/opt/foo/lib/libfoo.so.1.2.3``
-* ``/opt/foo/lib/libfoo.so.1.2 -> libfoo.so.1.2.3``
-* ``/opt/foo/lib/libfoo.so.1 -> libfoo.so.1.2``
-* ``/opt/foo/lib/libfoo.so -> libfoo.so.1``
+ .. note::
-and you do:
+ For a simple file copying operation, the :command:`file(COPY_FILE)`
+ sub-command just above may be easier to use.
-.. code-block:: cmake
+ .. versionadded:: 3.15
+ If ``FOLLOW_SYMLINK_CHAIN`` is specified, ``COPY`` will recursively resolve
+ the symlinks at the paths given until a real file is found, and install
+ a corresponding symlink in the destination for each symlink encountered.
+ For each symlink that is installed, the resolution is stripped of the
+ directory, leaving only the filename, meaning that the new symlink points
+ to a file in the same directory as the symlink. This feature is useful on
+ some Unix systems, where libraries are installed as a chain of symlinks
+ with version numbers, with less specific versions pointing to more specific
+ versions. ``FOLLOW_SYMLINK_CHAIN`` will install all of these symlinks and
+ the library itself into the destination directory. For example, if you have
+ the following directory structure:
- file(COPY /opt/foo/lib/libfoo.so DESTINATION lib FOLLOW_SYMLINK_CHAIN)
+ * ``/opt/foo/lib/libfoo.so.1.2.3``
+ * ``/opt/foo/lib/libfoo.so.1.2 -> libfoo.so.1.2.3``
+ * ``/opt/foo/lib/libfoo.so.1 -> libfoo.so.1.2``
+ * ``/opt/foo/lib/libfoo.so -> libfoo.so.1``
-This will install all of the symlinks and ``libfoo.so.1.2.3`` itself into
-``lib``.
+ and you do:
-See the :command:`install(DIRECTORY)` command for documentation of
-permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
-``EXCLUDE`` options. Copying directories preserves the structure
-of their content even if options are used to select a subset of
-files.
+ .. code-block:: cmake
-The ``INSTALL`` signature differs slightly from ``COPY``: it prints
-status messages, and ``NO_SOURCE_PERMISSIONS`` is default.
+ file(COPY /opt/foo/lib/libfoo.so DESTINATION lib FOLLOW_SYMLINK_CHAIN)
-Installation scripts generated by the :command:`install` command
-use this signature (with some undocumented options for internal use).
+ This will install all of the symlinks and ``libfoo.so.1.2.3`` itself into
+ ``lib``.
-.. versionchanged:: 3.22
+ See the :command:`install(DIRECTORY)` command for documentation of
+ permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
+ ``EXCLUDE`` options. Copying directories preserves the structure
+ of their content even if options are used to select a subset of
+ files.
- The environment variable :envvar:`CMAKE_INSTALL_MODE` can override the
- default copying behavior of :command:`file(INSTALL)`.
+ The ``INSTALL`` signature differs slightly from ``COPY``: it prints
+ status messages, and ``NO_SOURCE_PERMISSIONS`` is default. Installation
+ scripts generated by the :command:`install` command use this signature
+ (with some undocumented options for internal use).
-.. _SIZE:
+ .. versionchanged:: 3.22
-.. code-block:: cmake
+ The environment variable :envvar:`CMAKE_INSTALL_MODE` can override the
+ default copying behavior of :command:`file(INSTALL)`.
+.. signature::
file(SIZE <filename> <variable>)
-.. versionadded:: 3.14
-
-Determine the file size of the ``<filename>`` and put the result in
-``<variable>`` variable. Requires that ``<filename>`` is a valid path
-pointing to a file and is readable.
+ .. versionadded:: 3.14
-.. _READ_SYMLINK:
-
-.. code-block:: cmake
+ Determine the file size of the ``<filename>`` and put the result in
+ ``<variable>`` variable. Requires that ``<filename>`` is a valid path
+ pointing to a file and is readable.
+.. signature::
file(READ_SYMLINK <linkname> <variable>)
-.. versionadded:: 3.14
-
-This subcommand queries the symlink ``<linkname>`` and stores the path it
-points to in the result ``<variable>``. If ``<linkname>`` does not exist or
-is not a symlink, CMake issues a fatal error.
+ .. versionadded:: 3.14
-Note that this command returns the raw symlink path and does not resolve
-a relative path. The following is an example of how to ensure that an
-absolute path is obtained:
+ Query the symlink ``<linkname>`` and stores the path it points to
+ in the result ``<variable>``. If ``<linkname>`` does not exist
+ or is not a symlink, CMake issues a fatal error.
-.. code-block:: cmake
+ Note that this command returns the raw symlink path and does not resolve
+ a relative path. The following is an example of how to ensure that an
+ absolute path is obtained:
- set(linkname "/path/to/foo.sym")
- file(READ_SYMLINK "${linkname}" result)
- if(NOT IS_ABSOLUTE "${result}")
- get_filename_component(dir "${linkname}" DIRECTORY)
- set(result "${dir}/${result}")
- endif()
-
-.. _CREATE_LINK:
+ .. code-block:: cmake
-.. code-block:: cmake
+ set(linkname "/path/to/foo.sym")
+ file(READ_SYMLINK "${linkname}" result)
+ if(NOT IS_ABSOLUTE "${result}")
+ get_filename_component(dir "${linkname}" DIRECTORY)
+ set(result "${dir}/${result}")
+ endif()
+.. signature::
file(CREATE_LINK <original> <linkname>
[RESULT <result>] [COPY_ON_ERROR] [SYMBOLIC])
-.. versionadded:: 3.14
+ .. versionadded:: 3.14
-Create a link ``<linkname>`` that points to ``<original>``.
-It will be a hard link by default, but providing the ``SYMBOLIC`` option
-results in a symbolic link instead. Hard links require that ``original``
-exists and is a file, not a directory. If ``<linkname>`` already exists,
-it will be overwritten.
+ Create a link ``<linkname>`` that points to ``<original>``.
+ It will be a hard link by default, but providing the ``SYMBOLIC`` option
+ results in a symbolic link instead. Hard links require that ``original``
+ exists and is a file, not a directory. If ``<linkname>`` already exists,
+ it will be overwritten.
-The ``<result>`` variable, if specified, receives the status of the operation.
-It is set to ``0`` upon success or an error message otherwise. If ``RESULT``
-is not specified and the operation fails, a fatal error is emitted.
+ The ``<result>`` variable, if specified, receives the status of the
+ operation. It is set to ``0`` upon success or an error message otherwise.
+ If ``RESULT`` is not specified and the operation fails, a fatal error is
+ emitted.
-Specifying ``COPY_ON_ERROR`` enables copying the file as a fallback if
-creating the link fails. It can be useful for handling situations such as
-``<original>`` and ``<linkname>`` being on different drives or mount points,
-which would make them unable to support a hard link.
-
-.. _CHMOD:
-
-.. code-block:: cmake
+ Specifying ``COPY_ON_ERROR`` enables copying the file as a fallback if
+ creating the link fails. It can be useful for handling situations such as
+ ``<original>`` and ``<linkname>`` being on different drives or mount points,
+ which would make them unable to support a hard link.
+.. signature::
file(CHMOD <files>... <directories>...
- [PERMISSIONS <permissions>...]
- [FILE_PERMISSIONS <permissions>...]
- [DIRECTORY_PERMISSIONS <permissions>...])
-
-.. versionadded:: 3.19
-
-Set the permissions for the ``<files>...`` and ``<directories>...`` specified.
-Valid permissions are ``OWNER_READ``, ``OWNER_WRITE``, ``OWNER_EXECUTE``,
-``GROUP_READ``, ``GROUP_WRITE``, ``GROUP_EXECUTE``, ``WORLD_READ``,
-``WORLD_WRITE``, ``WORLD_EXECUTE``, ``SETUID``, ``SETGID``.
-
-Valid combination of keywords are:
+ [PERMISSIONS <permissions>...]
+ [FILE_PERMISSIONS <permissions>...]
+ [DIRECTORY_PERMISSIONS <permissions>...])
-``PERMISSIONS``
- All items are changed.
+ .. versionadded:: 3.19
-``FILE_PERMISSIONS``
- Only files are changed.
+ Set the permissions for the ``<files>...`` and ``<directories>...``
+ specified. Valid permissions are ``OWNER_READ``, ``OWNER_WRITE``,
+ ``OWNER_EXECUTE``, ``GROUP_READ``, ``GROUP_WRITE``, ``GROUP_EXECUTE``,
+ ``WORLD_READ``, ``WORLD_WRITE``, ``WORLD_EXECUTE``, ``SETUID``, ``SETGID``.
-``DIRECTORY_PERMISSIONS``
- Only directories are changed.
+ Valid combination of keywords are:
-``PERMISSIONS`` and ``FILE_PERMISSIONS``
- ``FILE_PERMISSIONS`` overrides ``PERMISSIONS`` for files.
+ ``PERMISSIONS``
+ All items are changed.
-``PERMISSIONS`` and ``DIRECTORY_PERMISSIONS``
- ``DIRECTORY_PERMISSIONS`` overrides ``PERMISSIONS`` for directories.
+ ``FILE_PERMISSIONS``
+ Only files are changed.
-``FILE_PERMISSIONS`` and ``DIRECTORY_PERMISSIONS``
- Use ``FILE_PERMISSIONS`` for files and ``DIRECTORY_PERMISSIONS`` for
- directories.
+ ``DIRECTORY_PERMISSIONS``
+ Only directories are changed.
+ ``PERMISSIONS`` and ``FILE_PERMISSIONS``
+ ``FILE_PERMISSIONS`` overrides ``PERMISSIONS`` for files.
-.. _CHMOD_RECURSE:
+ ``PERMISSIONS`` and ``DIRECTORY_PERMISSIONS``
+ ``DIRECTORY_PERMISSIONS`` overrides ``PERMISSIONS`` for directories.
-.. code-block:: cmake
+ ``FILE_PERMISSIONS`` and ``DIRECTORY_PERMISSIONS``
+ Use ``FILE_PERMISSIONS`` for files and ``DIRECTORY_PERMISSIONS`` for
+ directories.
+.. signature::
file(CHMOD_RECURSE <files>... <directories>...
[PERMISSIONS <permissions>...]
[FILE_PERMISSIONS <permissions>...]
[DIRECTORY_PERMISSIONS <permissions>...])
-.. versionadded:: 3.19
+ .. versionadded:: 3.19
+
+ Same as :cref:`CHMOD`, but change the permissions of files and directories
+ present in the ``<directories>...`` recursively.
-Same as `CHMOD`_, but change the permissions of files and directories present in
-the ``<directories>...`` recursively.
Path Conversion
^^^^^^^^^^^^^^^
-.. _REAL_PATH:
-
-.. code-block:: cmake
-
+.. signature::
file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
-.. versionadded:: 3.19
-
-Compute the absolute path to an existing file or directory with symlinks
-resolved.
-
-``BASE_DIRECTORY <dir>``
- If the provided ``<path>`` is a relative path, it is evaluated relative to the
- given base directory ``<dir>``. If no base directory is provided, the default
- base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`.
+ .. versionadded:: 3.19
-``EXPAND_TILDE``
- .. versionadded:: 3.21
+ Compute the absolute path to an existing file or directory with symlinks
+ resolved. The options are:
- If the ``<path>`` is ``~`` or starts with ``~/``, the ``~`` is replaced by
- the user's home directory. The path to the home directory is obtained from
- environment variables. On Windows, the ``USERPROFILE`` environment variable
- is used, falling back to the ``HOME`` environment variable if ``USERPROFILE``
- is not defined. On all other platforms, only ``HOME`` is used.
+ ``BASE_DIRECTORY <dir>``
+ If the provided ``<path>`` is a relative path, it is evaluated relative
+ to the given base directory ``<dir>``. If no base directory is provided,
+ the default base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`.
-.. _RELATIVE_PATH:
+ ``EXPAND_TILDE``
+ .. versionadded:: 3.21
-.. code-block:: cmake
+ If the ``<path>`` is ``~`` or starts with ``~/``, the ``~`` is replaced
+ by the user's home directory. The path to the home directory is obtained
+ from environment variables. On Windows, the ``USERPROFILE`` environment
+ variable is used, falling back to the ``HOME`` environment variable
+ if ``USERPROFILE`` is not defined. On all other platforms, only ``HOME``
+ is used.
+.. signature::
file(RELATIVE_PATH <variable> <directory> <file>)
-Compute the relative path from a ``<directory>`` to a ``<file>`` and
-store it in the ``<variable>``.
-
-.. _TO_CMAKE_PATH:
-.. _TO_NATIVE_PATH:
-
-.. code-block:: cmake
+ Compute the relative path from a ``<directory>`` to a ``<file>`` and
+ store it in the ``<variable>``.
+.. signature::
file(TO_CMAKE_PATH "<path>" <variable>)
file(TO_NATIVE_PATH "<path>" <variable>)
-The ``TO_CMAKE_PATH`` mode converts a native ``<path>`` into a cmake-style
-path with forward-slashes (``/``). The input can be a single path or a
-system search path like ``$ENV{PATH}``. A search path will be converted
-to a cmake-style list separated by ``;`` characters.
+ The ``TO_CMAKE_PATH`` mode converts a native ``<path>`` into a cmake-style
+ path with forward-slashes (``/``). The input can be a single path or a
+ system search path like ``$ENV{PATH}``. A search path will be converted
+ to a cmake-style list separated by ``;`` characters.
-The ``TO_NATIVE_PATH`` mode converts a cmake-style ``<path>`` into a native
-path with platform-specific slashes (``\`` on Windows hosts and ``/``
-elsewhere).
+ The ``TO_NATIVE_PATH`` mode converts a cmake-style ``<path>`` into a native
+ path with platform-specific slashes (``\`` on Windows hosts and ``/``
+ elsewhere).
-Always use double quotes around the ``<path>`` to be sure it is treated
-as a single argument to this command.
+ Always use double quotes around the ``<path>`` to be sure it is treated
+ as a single argument to this command.
Transfer
^^^^^^^^
-.. _DOWNLOAD:
-.. _UPLOAD:
+.. signature::
+ file(DOWNLOAD <url> [<file>] [<options>...])
+ file(UPLOAD <file> <url> [<options>...])
-.. code-block:: cmake
+ The ``DOWNLOAD`` subcommand downloads the given ``<url>`` to a local
+ ``<file>``. The ``UPLOAD`` mode uploads a local ``<file>`` to a given
+ ``<url>``.
- file(DOWNLOAD <url> [<file>] [<options>...])
- file(UPLOAD <file> <url> [<options>...])
+ .. versionadded:: 3.19
+ If ``<file>`` is not specified for ``file(DOWNLOAD)``, the file is not
+ saved. This can be useful if you want to know if a file can be downloaded
+ (for example, to check that it exists) without actually saving it anywhere.
-The ``DOWNLOAD`` subcommand downloads the given ``<url>`` to a local ``<file>``.
-The ``UPLOAD`` mode uploads a local ``<file>`` to a given ``<url>``.
+ Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
-.. versionadded:: 3.19
- If ``<file>`` is not specified for ``file(DOWNLOAD)``, the file is not saved.
- This can be useful if you want to know if a file can be downloaded (for example,
- to check that it exists) without actually saving it anywhere.
+ ``INACTIVITY_TIMEOUT <seconds>``
+ Terminate the operation after a period of inactivity.
-Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
+ ``LOG <variable>``
+ Store a human-readable log of the operation in a variable.
-``INACTIVITY_TIMEOUT <seconds>``
- Terminate the operation after a period of inactivity.
+ ``SHOW_PROGRESS``
+ Print progress information as status messages until the operation is
+ complete.
-``LOG <variable>``
- Store a human-readable log of the operation in a variable.
+ ``STATUS <variable>``
+ Store the resulting status of the operation in a variable.
+ The status is a ``;`` separated list of length 2.
+ The first element is the numeric return value for the operation,
+ and the second element is a string value for the error.
+ A ``0`` numeric error means no error in the operation.
-``SHOW_PROGRESS``
- Print progress information as status messages until the operation is
- complete.
+ ``TIMEOUT <seconds>``
+ Terminate the operation after a given total time has elapsed.
-``STATUS <variable>``
- Store the resulting status of the operation in a variable.
- The status is a ``;`` separated list of length 2.
- The first element is the numeric return value for the operation,
- and the second element is a string value for the error.
- A ``0`` numeric error means no error in the operation.
+ ``USERPWD <username>:<password>``
+ .. versionadded:: 3.7
-``TIMEOUT <seconds>``
- Terminate the operation after a given total time has elapsed.
+ Set username and password for operation.
-``USERPWD <username>:<password>``
- .. versionadded:: 3.7
+ ``HTTPHEADER <HTTP-header>``
+ .. versionadded:: 3.7
- Set username and password for operation.
+ HTTP header for ``DOWNLOAD`` and ``UPLOAD`` operations. ``HTTPHEADER``
+ can be repeated for multiple options:
-``HTTPHEADER <HTTP-header>``
- .. versionadded:: 3.7
+ .. code-block:: cmake
- HTTP header for ``DOWNLOAD`` and ``UPLOAD`` operations. ``HTTPHEADER`` can be
- repeated for multiple options:
+ file(DOWNLOAD <url>
+ HTTPHEADER "Authorization: Bearer <auth-token>"
+ HTTPHEADER "UserAgent: Mozilla/5.0")
- .. code-block:: cmake
+ ``NETRC <level>``
+ .. versionadded:: 3.11
- file(DOWNLOAD <url>
- HTTPHEADER "Authorization: Bearer <auth-token>"
- HTTPHEADER "UserAgent: Mozilla/5.0")
-
-``NETRC <level>``
- .. versionadded:: 3.11
-
- Specify whether the .netrc file is to be used for operation. If this
- option is not specified, the value of the :variable:`CMAKE_NETRC` variable
- will be used instead.
- Valid levels are:
-
- ``IGNORED``
- The .netrc file is ignored.
- This is the default.
- ``OPTIONAL``
- The .netrc file is optional, and information in the URL is preferred.
- The file will be scanned to find which ever information is not specified
- in the URL.
- ``REQUIRED``
- The .netrc file is required, and information in the URL is ignored.
-
-``NETRC_FILE <file>``
- .. versionadded:: 3.11
-
- Specify an alternative .netrc file to the one in your home directory,
- if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
- is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable will
- be used instead.
-
-``TLS_VERIFY <ON|OFF>``
- Specify whether to verify the server certificate for ``https://`` URLs.
- The default is to *not* verify. If this option is not specified, the value
- of the :variable:`CMAKE_TLS_VERIFY` variable will be used instead.
+ Specify whether the .netrc file is to be used for operation. If this
+ option is not specified, the value of the :variable:`CMAKE_NETRC`
+ variable will be used instead.
- .. versionadded:: 3.18
- Added support to ``file(UPLOAD)``.
+ Valid levels are:
-``TLS_CAINFO <file>``
- Specify a custom Certificate Authority file for ``https://`` URLs. If this
- option is not specified, the value of the :variable:`CMAKE_TLS_CAINFO`
- variable will be used instead.
+ ``IGNORED``
+ The .netrc file is ignored.
+ This is the default.
- .. versionadded:: 3.18
- Added support to ``file(UPLOAD)``.
+ ``OPTIONAL``
+ The .netrc file is optional, and information in the URL is preferred.
+ The file will be scanned to find which ever information is not
+ specified in the URL.
-For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL``
-certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to
-check certificates.
+ ``REQUIRED``
+ The .netrc file is required, and information in the URL is ignored.
-Additional options to ``DOWNLOAD`` are:
+ ``NETRC_FILE <file>``
+ .. versionadded:: 3.11
-``EXPECTED_HASH ALGO=<value>``
+ Specify an alternative .netrc file to the one in your home directory,
+ if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
+ is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable
+ will be used instead.
- Verify that the downloaded content hash matches the expected value, where
- ``ALGO`` is one of the algorithms supported by ``file(<HASH>)``.
- If the file already exists and matches the hash, the download is skipped.
- If the file already exists and does not match the hash, the file is
- downloaded again. If after download the file does not match the hash, the
- operation fails with an error. It is an error to specify this option if
- ``DOWNLOAD`` is not given a ``<file>``.
+ ``TLS_VERIFY <ON|OFF>``
+ Specify whether to verify the server certificate for ``https://`` URLs.
+ The default is to *not* verify. If this option is not specified, the
+ value of the :variable:`CMAKE_TLS_VERIFY` variable will be used instead.
-``EXPECTED_MD5 <value>``
- Historical short-hand for ``EXPECTED_HASH MD5=<value>``. It is an error to
- specify this if ``DOWNLOAD`` is not given a ``<file>``.
+ .. versionadded:: 3.18
+ Added support to ``file(UPLOAD)``.
-``RANGE_START <value>``
- .. versionadded:: 3.24
+ ``TLS_CAINFO <file>``
+ Specify a custom Certificate Authority file for ``https://`` URLs.
+ If this option is not specified, the value of the
+ :variable:`CMAKE_TLS_CAINFO` variable will be used instead.
- Offset of the start of the range in file in bytes. Could be omitted to
- download up to the specified ``RANGE_END``.
+ .. versionadded:: 3.18
+ Added support to ``file(UPLOAD)``.
-``RANGE_END <value>``
- .. versionadded:: 3.24
+ For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL``
+ certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to
+ check certificates.
- Offset of the end of the range in file in bytes. Could be omitted to
- download everything from the specified ``RANGE_START`` to the end of file.
+ Additional options to ``DOWNLOAD`` are:
-Locking
-^^^^^^^
+ ``EXPECTED_HASH <algorithm>=<value>``
+ Verify that the downloaded content hash matches the expected value, where
+ ``<algorithm>`` is one of the algorithms supported by :cref:`<HASH>`.
+ If the file already exists and matches the hash, the download is skipped.
+ If the file already exists and does not match the hash, the file is
+ downloaded again. If after download the file does not match the hash, the
+ operation fails with an error. It is an error to specify this option if
+ ``DOWNLOAD`` is not given a ``<file>``.
+
+ ``EXPECTED_MD5 <value>``
+ Historical short-hand for ``EXPECTED_HASH MD5=<value>``. It is an error
+ to specify this if ``DOWNLOAD`` is not given a ``<file>``.
-.. _LOCK:
+ ``RANGE_START <value>``
+ .. versionadded:: 3.24
-.. code-block:: cmake
+ Offset of the start of the range in file in bytes. Could be omitted to
+ download up to the specified ``RANGE_END``.
+ ``RANGE_END <value>``
+ .. versionadded:: 3.24
+
+ Offset of the end of the range in file in bytes. Could be omitted to
+ download everything from the specified ``RANGE_START`` to the end of
+ file.
+
+Locking
+^^^^^^^
+
+.. signature::
file(LOCK <path> [DIRECTORY] [RELEASE]
[GUARD <FUNCTION|FILE|PROCESS>]
[RESULT_VARIABLE <variable>]
[TIMEOUT <seconds>])
-.. versionadded:: 3.2
-
-Lock a file specified by ``<path>`` if no ``DIRECTORY`` option present and file
-``<path>/cmake.lock`` otherwise. File will be locked for scope defined by
-``GUARD`` option (default value is ``PROCESS``). ``RELEASE`` option can be used
-to unlock file explicitly. If option ``TIMEOUT`` is not specified CMake will
-wait until lock succeed or until fatal error occurs. If ``TIMEOUT`` is set to
-``0`` lock will be tried once and result will be reported immediately. If
-``TIMEOUT`` is not ``0`` CMake will try to lock file for the period specified
-by ``<seconds>`` value. Any errors will be interpreted as fatal if there is no
-``RESULT_VARIABLE`` option. Otherwise result will be stored in ``<variable>``
-and will be ``0`` on success or error message on failure.
-
-Note that lock is advisory - there is no guarantee that other processes will
-respect this lock, i.e. lock synchronize two or more CMake instances sharing
-some modifiable resources. Similar logic applied to ``DIRECTORY`` option -
-locking parent directory doesn't prevent other ``LOCK`` commands to lock any
-child directory or file.
-
-Trying to lock file twice is not allowed. Any intermediate directories and
-file itself will be created if they not exist. ``GUARD`` and ``TIMEOUT``
-options ignored on ``RELEASE`` operation.
+ .. versionadded:: 3.2
+
+ Lock a file specified by ``<path>`` if no ``DIRECTORY`` option present and
+ file ``<path>/cmake.lock`` otherwise. The file will be locked for the scope
+ defined by the ``GUARD`` option (default value is ``PROCESS``). The
+ ``RELEASE`` option can be used to unlock the file explicitly. If the
+ ``TIMEOUT`` option is not specified, CMake will wait until the lock succeeds
+ or until a fatal error occurs. If ``TIMEOUT`` is set to ``0``, locking will
+ be tried once and the result will be reported immediately. If ``TIMEOUT``
+ is not ``0``, CMake will try to lock the file for the period specified by
+ the ``TIMEOUT <seconds>`` value. Any errors will be interpreted as fatal if
+ there is no ``RESULT_VARIABLE`` option. Otherwise, the result will be stored
+ in ``<variable>`` and will be ``0`` on success or an error message on
+ failure.
+
+ Note that lock is advisory; there is no guarantee that other processes will
+ respect this lock, i.e. lock synchronize two or more CMake instances sharing
+ some modifiable resources. Similar logic applies to the ``DIRECTORY`` option;
+ locking a parent directory doesn't prevent other ``LOCK`` commands from
+ locking any child directory or file.
+
+ Trying to lock the same file twice is not allowed. Any intermediate
+ directories and the file itself will be created if they not exist. The
+ ``GUARD`` and ``TIMEOUT`` options are ignored on the ``RELEASE`` operation.
Archiving
^^^^^^^^^
-.. _ARCHIVE_CREATE:
-
-.. code-block:: cmake
-
+.. signature::
file(ARCHIVE_CREATE OUTPUT <archive>
PATHS <paths>...
[FORMAT <format>]
- [COMPRESSION <compression> [COMPRESSION_LEVEL <compression-level>]]
+ [COMPRESSION <compression>
+ [COMPRESSION_LEVEL <compression-level>]]
[MTIME <mtime>]
[VERBOSE])
+ :target: ARCHIVE_CREATE
+ :break: verbatim
-.. versionadded:: 3.18
-
-Creates the specified ``<archive>`` file with the files and directories
-listed in ``<paths>``. Note that ``<paths>`` must list actual files or
-directories, wildcards are not supported.
-
-Use the ``FORMAT`` option to specify the archive format. Supported values
-for ``<format>`` are ``7zip``, ``gnutar``, ``pax``, ``paxr``, ``raw`` and
-``zip``. If ``FORMAT`` is not given, the default format is ``paxr``.
+ .. versionadded:: 3.18
-Some archive formats allow the type of compression to be specified.
-The ``7zip`` and ``zip`` archive formats already imply a specific type of
-compression. The other formats use no compression by default, but can be
-directed to do so with the ``COMPRESSION`` option. Valid values for
-``<compression>`` are ``None``, ``BZip2``, ``GZip``, ``XZ``, and ``Zstd``.
+ Creates the specified ``<archive>`` file with the files and directories
+ listed in ``<paths>``. Note that ``<paths>`` must list actual files or
+ directories; wildcards are not supported.
-.. versionadded:: 3.19
- The compression level can be specified with the ``COMPRESSION_LEVEL`` option.
- The ``<compression-level>`` should be between 0-9, with the default being 0.
- The ``COMPRESSION`` option must be present when ``COMPRESSION_LEVEL`` is given.
+ Use the ``FORMAT`` option to specify the archive format. Supported values
+ for ``<format>`` are ``7zip``, ``gnutar``, ``pax``, ``paxr``, ``raw`` and
+ ``zip``. If ``FORMAT`` is not given, the default format is ``paxr``.
-.. versionadded:: 3.26
- The ``<compression-level>`` of the ``Zstd`` algorithm can be set between 0-19.
+ Some archive formats allow the type of compression to be specified.
+ The ``7zip`` and ``zip`` archive formats already imply a specific type of
+ compression. The other formats use no compression by default, but can be
+ directed to do so with the ``COMPRESSION`` option. Valid values for
+ ``<compression>`` are ``None``, ``BZip2``, ``GZip``, ``XZ``, and ``Zstd``.
-.. note::
- With ``FORMAT`` set to ``raw`` only one file will be compressed with the
- compression type specified by ``COMPRESSION``.
+ .. versionadded:: 3.19
+ The compression level can be specified with the ``COMPRESSION_LEVEL``
+ option. The ``<compression-level>`` should be between 0-9, with the
+ default being 0. The ``COMPRESSION`` option must be present when
+ ``COMPRESSION_LEVEL`` is given.
-The ``VERBOSE`` option enables verbose output for the archive operation.
+ .. versionadded:: 3.26
+ The ``<compression-level>`` of the ``Zstd`` algorithm can be set
+ between 0-19.
-To specify the modification time recorded in tarball entries, use
-the ``MTIME`` option.
+ .. note::
+ With ``FORMAT`` set to ``raw``, only one file will be compressed with the
+ compression type specified by ``COMPRESSION``.
-.. _ARCHIVE_EXTRACT:
+ The ``VERBOSE`` option enables verbose output for the archive operation.
-.. code-block:: cmake
+ To specify the modification time recorded in tarball entries, use
+ the ``MTIME`` option.
- file(ARCHIVE_EXTRACT INPUT <archive>
+.. signature::
+ file(ARCHIVE_EXTRACT
+ INPUT <archive>
[DESTINATION <dir>]
[PATTERNS <patterns>...]
[LIST_ONLY]
[VERBOSE]
[TOUCH])
+ :target: ARCHIVE_EXTRACT
-.. versionadded:: 3.18
+ .. versionadded:: 3.18
-Extracts or lists the content of the specified ``<archive>``.
+ Extracts or lists the content of the specified ``<archive>``.
-The directory where the content of the archive will be extracted to can
-be specified using the ``DESTINATION`` option. If the directory does not
-exist, it will be created. If ``DESTINATION`` is not given, the current
-binary directory will be used.
+ The directory where the content of the archive will be extracted to can
+ be specified using the ``DESTINATION`` option. If the directory does not
+ exist, it will be created. If ``DESTINATION`` is not given, the current
+ binary directory will be used.
-If required, you may select which files and directories to list or extract
-from the archive using the specified ``<patterns>``. Wildcards are supported.
-If the ``PATTERNS`` option is not given, the entire archive will be listed or
-extracted.
+ If required, you may select which files and directories to list or extract
+ from the archive using the specified ``<patterns>``. Wildcards are
+ supported. If the ``PATTERNS`` option is not given, the entire archive will
+ be listed or extracted.
-``LIST_ONLY`` will list the files in the archive rather than extract them.
+ ``LIST_ONLY`` will list the files in the archive rather than extract them.
-.. versionadded:: 3.24
- The ``TOUCH`` option gives extracted files a current local
- timestamp instead of extracting file timestamps from the archive.
+ .. versionadded:: 3.24
+ The ``TOUCH`` option gives extracted files a current local
+ timestamp instead of extracting file timestamps from the archive.
-With ``VERBOSE``, the command will produce verbose output.
+ With ``VERBOSE``, the command will produce verbose output.
diff --git a/Help/command/get_filename_component.rst b/Help/command/get_filename_component.rst
index 899ede6..7d74a33 100644
--- a/Help/command/get_filename_component.rst
+++ b/Help/command/get_filename_component.rst
@@ -4,9 +4,9 @@ get_filename_component
Get a specific component of a full filename.
.. versionchanged:: 3.20
- This command has been superseded by :command:`cmake_path` command, except
- ``REALPATH`` now offered by :ref:`file(REAL_PATH)<REAL_PATH>` command and
- ``PROGRAM`` now available in :command:`separate_arguments(PROGRAM)` command.
+ This command has been superseded by the :command:`cmake_path` command, except
+ for ``REALPATH``, which is now offered by :command:`file(REAL_PATH)`, and
+ ``PROGRAM``, now available in :command:`separate_arguments(PROGRAM)`.
.. versionchanged:: 3.24
The undocumented feature offering the capability to query the ``Windows``
diff --git a/Help/command/list.rst b/Help/command/list.rst
index 33c4f80..191003a 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -36,23 +36,25 @@ Synopsis
Introduction
^^^^^^^^^^^^
-The list subcommands ``APPEND``, ``INSERT``, ``FILTER``, ``PREPEND``,
-``POP_BACK``, ``POP_FRONT``, ``REMOVE_AT``, ``REMOVE_ITEM``,
-``REMOVE_DUPLICATES``, ``REVERSE`` and ``SORT`` may create
-new values for the list within the current CMake variable scope. Similar to
-the :command:`set` command, the LIST command creates new variable values in
-the current scope, even if the list itself is actually defined in a parent
-scope. To propagate the results of these operations upwards, use
-:command:`set` with ``PARENT_SCOPE``, :command:`set` with
-``CACHE INTERNAL``, or some other means of value propagation.
+The list subcommands :cref:`APPEND`, :cref:`INSERT`, :cref:`FILTER`,
+:cref:`PREPEND`, :cref:`POP_BACK`, :cref:`POP_FRONT`, :cref:`REMOVE_AT`,
+:cref:`REMOVE_ITEM`, :cref:`REMOVE_DUPLICATES`, :cref:`REVERSE` and
+:cref:`SORT` may create new values for the list within the current CMake
+variable scope. Similar to the :command:`set` command, the ``list`` command
+creates new variable values in the current scope, even if the list itself is
+actually defined in a parent scope. To propagate the results of these
+operations upwards, use :command:`set` with ``PARENT_SCOPE``,
+:command:`set` with ``CACHE INTERNAL``, or some other means of value
+propagation.
.. note::
A list in cmake is a ``;`` separated group of strings. To create a
- list the set command can be used. For example, ``set(var a b c d e)``
- creates a list with ``a;b;c;d;e``, and ``set(var "a b c d e")`` creates a
- string or a list with one item in it. (Note macro arguments are not
- variables, and therefore cannot be used in LIST commands.)
+ list, the :command:`set` command can be used. For example,
+ ``set(var a b c d e)`` creates a list with ``a;b;c;d;e``, and
+ ``set(var "a b c d e")`` creates a string or a list with one item in it.
+ (Note that macro arguments are not variables, and therefore cannot be used
+ in ``LIST`` commands.)
.. note::
@@ -66,76 +68,54 @@ scope. To propagate the results of these operations upwards, use
Reading
^^^^^^^
-.. _LENGTH:
-
-.. code-block:: cmake
-
+.. signature::
list(LENGTH <list> <output variable>)
-Returns the list's length.
-
-.. _GET:
-
-.. code-block:: cmake
+ Returns the list's length.
+.. signature::
list(GET <list> <element index> [<element index> ...] <output variable>)
-Returns the list of elements specified by indices from the list.
-
-.. _JOIN:
+ Returns the list of elements specified by indices from the list.
-.. code-block:: cmake
+.. signature:: list(JOIN <list> <glue> <output variable>)
- list(JOIN <list> <glue> <output variable>)
+ .. versionadded:: 3.12
-.. versionadded:: 3.12
-
-Returns a string joining all list's elements using the glue string.
-To join multiple strings, which are not part of a list, use ``JOIN`` operator
-from :command:`string` command.
-
-.. _SUBLIST:
-
-.. code-block:: cmake
+ Returns a string joining all list's elements using the glue string.
+ To join multiple strings, which are not part of a list,
+ use :command:`string(JOIN)`.
+.. signature::
list(SUBLIST <list> <begin> <length> <output variable>)
-.. versionadded:: 3.12
+ .. versionadded:: 3.12
-Returns a sublist of the given list.
-If ``<length>`` is 0, an empty list will be returned.
-If ``<length>`` is -1 or the list is smaller than ``<begin>+<length>`` then
-the remaining elements of the list starting at ``<begin>`` will be returned.
+ Returns a sublist of the given list.
+ If ``<length>`` is 0, an empty list will be returned.
+ If ``<length>`` is -1 or the list is smaller than ``<begin>+<length>`` then
+ the remaining elements of the list starting at ``<begin>`` will be returned.
Search
^^^^^^
-.. _FIND:
-
-.. code-block:: cmake
-
+.. signature::
list(FIND <list> <value> <output variable>)
-Returns the index of the element specified in the list or -1
-if it wasn't found.
+ Returns the index of the element specified in the list
+ or ``-1`` if it wasn't found.
Modification
^^^^^^^^^^^^
-.. _APPEND:
-
-.. code-block:: cmake
-
+.. signature::
list(APPEND <list> [<element> ...])
-Appends elements to the list. If no variable named ``<list>`` exists in the
-current scope its value is treated as empty and the elements are appended to
-that empty list.
-
-.. _FILTER:
-
-.. code-block:: cmake
+ Appends elements to the list. If no variable named ``<list>`` exists in the
+ current scope its value is treated as empty and the elements are appended to
+ that empty list.
+.. signature::
list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
.. versionadded:: 3.6
@@ -146,219 +126,205 @@ In ``REGEX`` mode, items will be matched against the given regular expression.
For more information on regular expressions look under
:ref:`string(REGEX) <Regex Specification>`.
-.. _INSERT:
-
-.. code-block:: cmake
-
+.. signature::
list(INSERT <list> <element_index> <element> [<element> ...])
-Inserts elements to the list to the specified index. It is an
-error to specify an out-of-range index. Valid indexes are 0 to `N`
-where `N` is the length of the list, inclusive. An empty list
-has length 0. If no variable named ``<list>`` exists in the
-current scope its value is treated as empty and the elements are
-inserted in that empty list.
-
-.. _POP_BACK:
-
-.. code-block:: cmake
+ Inserts elements to the list to the specified index. It is an
+ error to specify an out-of-range index. Valid indexes are 0 to `N`
+ where `N` is the length of the list, inclusive. An empty list
+ has length 0. If no variable named ``<list>`` exists in the
+ current scope its value is treated as empty and the elements are
+ inserted in that empty list.
+.. signature::
list(POP_BACK <list> [<out-var>...])
-.. versionadded:: 3.15
+ .. versionadded:: 3.15
-If no variable name is given, removes exactly one element. Otherwise,
-with `N` variable names provided, assign the last `N` elements' values
-to the given variables and then remove the last `N` values from
-``<list>``.
-
-.. _POP_FRONT:
-
-.. code-block:: cmake
+ If no variable name is given, removes exactly one element. Otherwise,
+ with `N` variable names provided, assign the last `N` elements' values
+ to the given variables and then remove the last `N` values from
+ ``<list>``.
+.. signature::
list(POP_FRONT <list> [<out-var>...])
-.. versionadded:: 3.15
-
-If no variable name is given, removes exactly one element. Otherwise,
-with `N` variable names provided, assign the first `N` elements' values
-to the given variables and then remove the first `N` values from
-``<list>``.
+ .. versionadded:: 3.15
-.. _PREPEND:
-
-.. code-block:: cmake
+ If no variable name is given, removes exactly one element. Otherwise,
+ with `N` variable names provided, assign the first `N` elements' values
+ to the given variables and then remove the first `N` values from
+ ``<list>``.
+.. signature::
list(PREPEND <list> [<element> ...])
-.. versionadded:: 3.15
-
-Insert elements to the 0th position in the list. If no variable named
-``<list>`` exists in the current scope its value is treated as empty and
-the elements are prepended to that empty list.
+ .. versionadded:: 3.15
-.. _REMOVE_ITEM:
-
-.. code-block:: cmake
+ Insert elements to the 0th position in the list. If no variable named
+ ``<list>`` exists in the current scope its value is treated as empty and
+ the elements are prepended to that empty list.
+.. signature::
list(REMOVE_ITEM <list> <value> [<value> ...])
-Removes all instances of the given items from the list.
-
-.. _REMOVE_AT:
-
-.. code-block:: cmake
+ Removes all instances of the given items from the list.
+.. signature::
list(REMOVE_AT <list> <index> [<index> ...])
-Removes items at given indices from the list.
-
-.. _REMOVE_DUPLICATES:
-
-.. code-block:: cmake
+ Removes items at given indices from the list.
+.. signature::
list(REMOVE_DUPLICATES <list>)
-Removes duplicated items in the list. The relative order of items is preserved,
-but if duplicates are encountered, only the first instance is preserved.
-
-.. _TRANSFORM:
-
-.. code-block:: cmake
+ Removes duplicated items in the list. The relative order of items
+ is preserved, but if duplicates are encountered,
+ only the first instance is preserved.
+.. signature::
list(TRANSFORM <list> <ACTION> [<SELECTOR>]
- [OUTPUT_VARIABLE <output variable>])
+ [OUTPUT_VARIABLE <output variable>])
-.. versionadded:: 3.12
+ .. versionadded:: 3.12
-Transforms the list by applying an action to all or, by specifying a
-``<SELECTOR>``, to the selected elements of the list, storing the result
-in-place or in the specified output variable.
+ Transforms the list by applying an action to all or, by specifying a
+ ``<SELECTOR>``, to the selected elements of the list, storing the result
+ in-place or in the specified output variable.
-.. note::
+ .. note::
- The ``TRANSFORM`` sub-command does not change the number of elements in the
- list. If a ``<SELECTOR>`` is specified, only some elements will be changed,
- the other ones will remain the same as before the transformation.
+ The ``TRANSFORM`` sub-command does not change the number of elements in the
+ list. If a ``<SELECTOR>`` is specified, only some elements will be changed,
+ the other ones will remain the same as before the transformation.
-``<ACTION>`` specifies the action to apply to the elements of the list.
-The actions have exactly the same semantics as sub-commands of the
-:command:`string` command. ``<ACTION>`` must be one of the following:
+ ``<ACTION>`` specifies the action to apply to the elements of the list.
+ The actions have exactly the same semantics as sub-commands of the
+ :command:`string` command. ``<ACTION>`` must be one of the following:
-``APPEND``, ``PREPEND``: Append, prepend specified value to each element of
-the list.
+ :command:`APPEND <string(APPEND)>`, :command:`PREPEND <string(PREPEND)>`
+ Append, prepend specified value to each element of the list.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> <APPEND|PREPEND> <value> ...)
+ list(TRANSFORM <list> <APPEND|PREPEND> <value> ...)
-``TOUPPER``, ``TOLOWER``: Convert each element of the list to upper, lower
-characters.
+ :command:`TOUPPER <string(TOUPPER)>`, :command:`TOLOWER <string(TOLOWER)>`
+ Convert each element of the list to upper, lower characters.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> <TOLOWER|TOUPPER> ...)
+ list(TRANSFORM <list> <TOLOWER|TOUPPER> ...)
-``STRIP``: Remove leading and trailing spaces from each element of the
-list.
+ :command:`STRIP <string(STRIP)>`
+ Remove leading and trailing spaces from each element of the list.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> STRIP ...)
+ list(TRANSFORM <list> STRIP ...)
-``GENEX_STRIP``: Strip any
-:manual:`generator expressions <cmake-generator-expressions(7)>` from each
-element of the list.
+ :command:`GENEX_STRIP <string(GENEX_STRIP)>`
+ Strip any
+ :manual:`generator expressions <cmake-generator-expressions(7)>`
+ from each element of the list.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> GENEX_STRIP ...)
+ list(TRANSFORM <list> GENEX_STRIP ...)
-``REPLACE``: Match the regular expression as many times as possible and
-substitute the replacement expression for the match for each element
-of the list
-(Same semantic as ``REGEX REPLACE`` from :command:`string` command).
+ :command:`REPLACE <string(REGEX REPLACE)>`:
+ Match the regular expression as many times as possible and substitute
+ the replacement expression for the match for each element of the list
+ (same semantic as :command:`string(REGEX REPLACE)`).
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> REPLACE <regular_expression>
- <replace_expression> ...)
+ list(TRANSFORM <list> REPLACE <regular_expression>
+ <replace_expression> ...)
-``<SELECTOR>`` determines which elements of the list will be transformed.
-Only one type of selector can be specified at a time. When given,
-``<SELECTOR>`` must be one of the following:
+ ``<SELECTOR>`` determines which elements of the list will be transformed.
+ Only one type of selector can be specified at a time.
+ When given, ``<SELECTOR>`` must be one of the following:
-``AT``: Specify a list of indexes.
+ ``AT``
+ Specify a list of indexes.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> <ACTION> AT <index> [<index> ...] ...)
+ list(TRANSFORM <list> <ACTION> AT <index> [<index> ...] ...)
-``FOR``: Specify a range with, optionally, an increment used to iterate over
-the range.
+ ``FOR``
+ Specify a range with, optionally,
+ an increment used to iterate over the range.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> <ACTION> FOR <start> <stop> [<step>] ...)
+ list(TRANSFORM <list> <ACTION> FOR <start> <stop> [<step>] ...)
-``REGEX``: Specify a regular expression. Only elements matching the regular
-expression will be transformed.
+ ``REGEX``
+ Specify a regular expression.
+ Only elements matching the regular expression will be transformed.
- .. code-block:: cmake
+ .. code-block:: cmake
- list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...)
+ list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...)
Ordering
^^^^^^^^
-.. _REVERSE:
+.. signature::
+ list(REVERSE <list>)
-.. code-block:: cmake
+ Reverses the contents of the list in-place.
- list(REVERSE <list>)
+.. signature::
+ list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
-Reverses the contents of the list in-place.
+ Sorts the list in-place alphabetically.
-.. _SORT:
+ .. versionadded:: 3.13
+ Added the ``COMPARE``, ``CASE``, and ``ORDER`` options.
-.. code-block:: cmake
+ .. versionadded:: 3.18
+ Added the ``COMPARE NATURAL`` option.
- list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
+ Use the ``COMPARE`` keyword to select the comparison method for sorting.
+ The ``<compare>`` option should be one of:
-Sorts the list in-place alphabetically.
+ ``STRING``
+ Sorts a list of strings alphabetically.
+ This is the default behavior if the ``COMPARE`` option is not given.
-.. versionadded:: 3.13
- Added the ``COMPARE``, ``CASE``, and ``ORDER`` options.
+ ``FILE_BASENAME``
+ Sorts a list of pathnames of files by their basenames.
-.. versionadded:: 3.18
- Added the ``COMPARE NATURAL`` option.
+ ``NATURAL``
+ Sorts a list of strings using natural order
+ (see ``strverscmp(3)`` manual), i.e. such that contiguous digits
+ are compared as whole numbers.
+ For example: the following list `10.0 1.1 2.1 8.0 2.0 3.1`
+ will be sorted as `1.1 2.0 2.1 3.1 8.0 10.0` if the ``NATURAL``
+ comparison is selected where it will be sorted as
+ `1.1 10.0 2.0 2.1 3.1 8.0` with the ``STRING`` comparison.
-Use the ``COMPARE`` keyword to select the comparison method for sorting.
-The ``<compare>`` option should be one of:
+ Use the ``CASE`` keyword to select a case sensitive or case insensitive
+ sort mode. The ``<case>`` option should be one of:
-* ``STRING``: Sorts a list of strings alphabetically. This is the
- default behavior if the ``COMPARE`` option is not given.
-* ``FILE_BASENAME``: Sorts a list of pathnames of files by their basenames.
-* ``NATURAL``: Sorts a list of strings using natural order
- (see ``strverscmp(3)`` manual), i.e. such that contiguous digits
- are compared as whole numbers.
- For example: the following list `10.0 1.1 2.1 8.0 2.0 3.1`
- will be sorted as `1.1 2.0 2.1 3.1 8.0 10.0` if the ``NATURAL``
- comparison is selected where it will be sorted as
- `1.1 10.0 2.0 2.1 3.1 8.0` with the ``STRING`` comparison.
+ ``SENSITIVE``
+ List items are sorted in a case-sensitive manner.
+ This is the default behavior if the ``CASE`` option is not given.
-Use the ``CASE`` keyword to select a case sensitive or case insensitive
-sort mode. The ``<case>`` option should be one of:
+ ``INSENSITIVE``
+ List items are sorted case insensitively. The order of
+ items which differ only by upper/lowercase is not specified.
-* ``SENSITIVE``: List items are sorted in a case-sensitive manner. This is
- the default behavior if the ``CASE`` option is not given.
-* ``INSENSITIVE``: List items are sorted case insensitively. The order of
- items which differ only by upper/lowercase is not specified.
+ To control the sort order, the ``ORDER`` keyword can be given.
+ The ``<order>`` option should be one of:
-To control the sort order, the ``ORDER`` keyword can be given.
-The ``<order>`` option should be one of:
+ ``ASCENDING``
+ Sorts the list in ascending order.
+ This is the default behavior when the ``ORDER`` option is not given.
-* ``ASCENDING``: Sorts the list in ascending order. This is the default
- behavior when the ``ORDER`` option is not given.
-* ``DESCENDING``: Sorts the list in descending order.
+ ``DESCENDING``
+ Sorts the list in descending order.
diff --git a/Help/command/set.rst b/Help/command/set.rst
index c724844..ee677c9 100644
--- a/Help/command/set.rst
+++ b/Help/command/set.rst
@@ -15,102 +15,107 @@ unset. See the :command:`unset` command to unset variables explicitly.
Set Normal Variable
^^^^^^^^^^^^^^^^^^^
-.. code-block:: cmake
-
+.. signature::
set(<variable> <value>... [PARENT_SCOPE])
+ :target: normal
-Sets the given ``<variable>`` in the current function or directory scope.
+ Sets the given ``<variable>`` in the current function or directory scope.
-If the ``PARENT_SCOPE`` option is given the variable will be set in
-the scope above the current scope. Each new directory or :command:`function`
-command creates a new scope. A scope can also be created with the
-:command:`block` command. This command will set the value of a variable into
-the parent directory, calling function or encompassing scope (whichever is
-applicable to the case at hand). The previous state of the variable's value
-stays the same in the current scope (e.g., if it was undefined before, it is
-still undefined and if it had a value, it is still that value).
+ If the ``PARENT_SCOPE`` option is given the variable will be set in
+ the scope above the current scope. Each new directory or :command:`function`
+ command creates a new scope. A scope can also be created with the
+ :command:`block` command. This command will set the value of a variable into
+ the parent directory, calling function or encompassing scope (whichever is
+ applicable to the case at hand). The previous state of the variable's value
+ stays the same in the current scope (e.g., if it was undefined before, it is
+ still undefined and if it had a value, it is still that value).
-The :command:`block(PROPAGATE)` and :command:`return(PROPAGATE)` commands can
-be used as an alternate method to the :command:`set(PARENT_SCOPE)` and
-:command:`unset(PARENT_SCOPE)` commands to update the parent scope.
+ The :command:`block(PROPAGATE)` and :command:`return(PROPAGATE)` commands
+ can be used as an alternate method to the :command:`set(PARENT_SCOPE)`
+ and :command:`unset(PARENT_SCOPE)` commands to update the parent scope.
Set Cache Entry
^^^^^^^^^^^^^^^
-.. code-block:: cmake
-
+.. signature::
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
-
-Sets the given cache ``<variable>`` (cache entry). Since cache entries
-are meant to provide user-settable values this does not overwrite
-existing cache entries by default. Use the ``FORCE`` option to
-overwrite existing entries.
-
-The ``<type>`` must be specified as one of:
-
-``BOOL``
- Boolean ``ON/OFF`` value. :manual:`cmake-gui(1)` offers a checkbox.
-
-``FILEPATH``
- Path to a file on disk. :manual:`cmake-gui(1)` offers a file dialog.
-
-``PATH``
- Path to a directory on disk. :manual:`cmake-gui(1)` offers a file dialog.
-
-``STRING``
- A line of text. :manual:`cmake-gui(1)` offers a text field or a
- drop-down selection if the :prop_cache:`STRINGS` cache entry
- property is set.
-
-``INTERNAL``
- A line of text. :manual:`cmake-gui(1)` does not show internal entries.
- They may be used to store variables persistently across runs.
- Use of this type implies ``FORCE``.
-
-The ``<docstring>`` must be specified as a line of text providing
-a quick summary of the option for presentation to :manual:`cmake-gui(1)`
-users.
-
-If the cache entry does not exist prior to the call or the ``FORCE``
-option is given then the cache entry will be set to the given value.
-
-.. note::
-
- The content of the cache variable will not be directly accessible if a normal
- variable of the same name already exists (see :ref:`rules of variable
- evaluation <CMake Language Variables>`). If policy :policy:`CMP0126` is set
- to ``OLD``, any normal variable binding in the current scope will be removed.
-
-It is possible for the cache entry to exist prior to the call but
-have no type set if it was created on the :manual:`cmake(1)` command
-line by a user through the :option:`-D\<var\>=\<value\> <cmake -D>` option without
-specifying a type. In this case the ``set`` command will add the
-type. Furthermore, if the ``<type>`` is ``PATH`` or ``FILEPATH``
-and the ``<value>`` provided on the command line is a relative path,
-then the ``set`` command will treat the path as relative to the
-current working directory and convert it to an absolute path.
+ :target: CACHE
+
+ Sets the given cache ``<variable>`` (cache entry). Since cache entries
+ are meant to provide user-settable values this does not overwrite
+ existing cache entries by default. Use the ``FORCE`` option to
+ overwrite existing entries.
+
+ The ``<type>`` must be specified as one of:
+
+ ``BOOL``
+ Boolean ``ON/OFF`` value.
+ :manual:`cmake-gui(1)` offers a checkbox.
+
+ ``FILEPATH``
+ Path to a file on disk.
+ :manual:`cmake-gui(1)` offers a file dialog.
+
+ ``PATH``
+ Path to a directory on disk.
+ :manual:`cmake-gui(1)` offers a file dialog.
+
+ ``STRING``
+ A line of text.
+ :manual:`cmake-gui(1)` offers a text field or a drop-down selection
+ if the :prop_cache:`STRINGS` cache entry property is set.
+
+ ``INTERNAL``
+ A line of text.
+ :manual:`cmake-gui(1)` does not show internal entries.
+ They may be used to store variables persistently across runs.
+ Use of this type implies ``FORCE``.
+
+ The ``<docstring>`` must be specified as a line of text
+ providing a quick summary of the option
+ for presentation to :manual:`cmake-gui(1)` users.
+
+ If the cache entry does not exist prior to the call or the ``FORCE``
+ option is given then the cache entry will be set to the given value.
+
+ .. note::
+
+ The content of the cache variable will not be directly accessible
+ if a normal variable of the same name already exists
+ (see :ref:`rules of variable evaluation <CMake Language Variables>`).
+ If policy :policy:`CMP0126` is set to ``OLD``, any normal variable
+ binding in the current scope will be removed.
+
+ It is possible for the cache entry to exist prior to the call but
+ have no type set if it was created on the :manual:`cmake(1)` command
+ line by a user through the :option:`-D\<var\>=\<value\> <cmake -D>` option
+ without specifying a type. In this case the ``set`` command will add the
+ type. Furthermore, if the ``<type>`` is ``PATH`` or ``FILEPATH``
+ and the ``<value>`` provided on the command line is a relative path,
+ then the ``set`` command will treat the path as relative to the
+ current working directory and convert it to an absolute path.
Set Environment Variable
^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block:: cmake
-
+.. signature::
set(ENV{<variable>} [<value>])
+ :target: ENV
-Sets an :manual:`Environment Variable <cmake-env-variables(7)>`
-to the given value.
-Subsequent calls of ``$ENV{<variable>}`` will return this new value.
+ Sets an :manual:`Environment Variable <cmake-env-variables(7)>`
+ to the given value.
+ Subsequent calls of ``$ENV{<variable>}`` will return this new value.
-This command affects only the current CMake process, not the process
-from which CMake was called, nor the system environment at large,
-nor the environment of subsequent build or test processes.
+ This command affects only the current CMake process, not the process
+ from which CMake was called, nor the system environment at large,
+ nor the environment of subsequent build or test processes.
-If no argument is given after ``ENV{<variable>}`` or if ``<value>`` is
-an empty string, then this command will clear any existing value of the
-environment variable.
+ If no argument is given after ``ENV{<variable>}`` or if ``<value>`` is
+ an empty string, then this command will clear any existing value of the
+ environment variable.
-Arguments after ``<value>`` are ignored. If extra arguments are found,
-then an author warning is issued.
+ Arguments after ``<value>`` are ignored. If extra arguments are found,
+ then an author warning is issued.
See Also
^^^^^^^^
diff --git a/Help/command/string.rst b/Help/command/string.rst
index b47fa09..e226aa1 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -32,7 +32,7 @@ Synopsis
string(`COMPARE`_ <op> <string1> <string2> <out-var>)
`Hashing`_
- string(`\<HASH\> <HASH_>`_ <out-var> <input>)
+ string(`\<HASH\>`_ <out-var> <input>)
`Generation`_
string(`ASCII`_ <number>... <out-var>)
@@ -299,7 +299,7 @@ Hashing
.. signature::
string(<HASH> <output_variable> <input>)
- :target: HASH
+ :target: <HASH>
Compute a cryptographic hash of the ``<input>`` string.
The supported ``<HASH>`` algorithm names are:
diff --git a/Help/dev/documentation.rst b/Help/dev/documentation.rst
index 8cd71b4..c6fb7a6 100644
--- a/Help/dev/documentation.rst
+++ b/Help/dev/documentation.rst
@@ -241,6 +241,10 @@ Document a "genex" object:
The directive requires a single argument, the generator expression name.
+The optional ``:target:`` option allows a custom target name to be specified.
+Because this will affect the ability to reference the "genex" object using the
+``:genex:`` role, this option should be used very sparingly.
+
``signature`` directive
^^^^^^^^^^^^^^^^^^^^^^^
@@ -301,6 +305,23 @@ The ``signature`` directive generates a hyperlink target for each signature:
headers, the targets do not work with Sphinx ``:ref:`` syntax, however
they can be globally referenced using e.g. ``:command:`string(APPEND)```.
+Although whitespace in the signature is not preserved, by default, line breaks
+are suppressed inside of square- or angle-brackets. This behavior can be
+controlled using the ``:break:`` option; note, however, that there is no way
+to *force* a line break. The default value is 'smart'. Allowable values are:
+
+ ``all``
+ Allow line breaks at any whitespace.
+
+ ``smart`` (default)
+ Allow line breaks at whitespace, except between matched square- or
+ angle-brackets. For example, if a signature contains the text
+ ``<input>... [OUTPUT_VARIABLE <out-var>]``, a line break would be allowed
+ after ``<input>...`` but not between ``OUTPUT_VARIABLE`` and ``<out-var>``.
+
+ ``verbatim``
+ Allow line breaks only where the source document contains a newline.
+
The directive treats its content as the documentation of the signature(s).
Indent the signature documentation accordingly.
@@ -374,6 +395,10 @@ object names like ``OUTPUT_NAME_<CONFIG>``. The form ``a <b>``,
with a space preceding ``<``, is still interpreted as a link text
with an explicit target.
+Additionally, the ``cref`` role may be used to create references
+to local targets that have literal styling. This is especially
+useful for referencing a subcommand in the command's documentation.
+
.. _`list()`: https://cmake.org/cmake/help/latest/command/list.html
.. _`list(APPEND)`: https://cmake.org/cmake/help/latest/command/list.html
.. _`list(APPEND) sub-command`: https://cmake.org/cmake/help/latest/command/list.html
diff --git a/Help/envvar/CMAKE_MAXIMUM_RECURSION_DEPTH.rst b/Help/envvar/CMAKE_MAXIMUM_RECURSION_DEPTH.rst
new file mode 100644
index 0000000..2d65b60
--- /dev/null
+++ b/Help/envvar/CMAKE_MAXIMUM_RECURSION_DEPTH.rst
@@ -0,0 +1,10 @@
+CMAKE_MAXIMUM_RECURSION_DEPTH
+-----------------------------
+
+.. versionadded:: 3.27
+
+.. include:: ENV_VAR.txt
+
+Maximum recursion depth for CMake scripts. This environment variable is
+used if the :variable:`CMAKE_MAXIMUM_RECURSION_DEPTH` variable is not set.
+See that variable's documentation for details.
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index 4c29b80..1f0c911 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -20,6 +20,7 @@ Environment Variables that Change Behavior
.. toctree::
:maxdepth: 1
+ /envvar/CMAKE_MAXIMUM_RECURSION_DEPTH
/envvar/CMAKE_PREFIX_PATH
/envvar/SSL_CERT_DIR
/envvar/SSL_CERT_FILE
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index a640c13..9da3799 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -1418,6 +1418,7 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
expression is being evaluated.
.. genex:: $<TARGET_PROPERTY:prop>
+ :target: TARGET_PROPERTY:prop
Value of the property ``prop`` on the target for which the expression
is being evaluated. Note that for generator expressions in
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 01c9ce8..8559b0b 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -175,7 +175,10 @@ Properties on Targets
/prop_tgt/CONFIG_POSTFIX
/prop_tgt/CROSSCOMPILING_EMULATOR
/prop_tgt/CUDA_ARCHITECTURES
+ /prop_tgt/CUDA_CUBIN_COMPILATION
/prop_tgt/CUDA_EXTENSIONS
+ /prop_tgt/CUDA_FATBIN_COMPILATION
+ /prop_tgt/CUDA_OPTIX_COMPILATION
/prop_tgt/CUDA_PTX_COMPILATION
/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS
/prop_tgt/CUDA_RUNTIME_LIBRARY
diff --git a/Help/prop_tgt/CUDA_CUBIN_COMPILATION.rst b/Help/prop_tgt/CUDA_CUBIN_COMPILATION.rst
new file mode 100644
index 0000000..f8860ae
--- /dev/null
+++ b/Help/prop_tgt/CUDA_CUBIN_COMPILATION.rst
@@ -0,0 +1,14 @@
+CUDA_CUBIN_COMPILATION
+----------------------
+
+.. versionadded:: 3.27
+
+Compile CUDA sources to ``.cubin`` files instead of ``.obj`` files
+within :ref:`Object Libraries`.
+
+For example:
+
+.. code-block:: cmake
+
+ add_library(mycubin OBJECT a.cu b.cu)
+ set_property(TARGET mycubin PROPERTY CUDA_CUBIN_COMPILATION ON)
diff --git a/Help/prop_tgt/CUDA_FATBIN_COMPILATION.rst b/Help/prop_tgt/CUDA_FATBIN_COMPILATION.rst
new file mode 100644
index 0000000..3d3c715
--- /dev/null
+++ b/Help/prop_tgt/CUDA_FATBIN_COMPILATION.rst
@@ -0,0 +1,14 @@
+CUDA_FATBIN_COMPILATION
+-----------------------
+
+.. versionadded:: 3.27
+
+Compile CUDA sources to ``.fatbin`` files instead of ``.obj`` files
+within :ref:`Object Libraries`.
+
+For example:
+
+.. code-block:: cmake
+
+ add_library(myfbins OBJECT a.cu b.cu)
+ set_property(TARGET myfbins PROPERTY CUDA_FATBIN_COMPILATION ON)
diff --git a/Help/prop_tgt/CUDA_OPTIX_COMPILATION.rst b/Help/prop_tgt/CUDA_OPTIX_COMPILATION.rst
new file mode 100644
index 0000000..c2a06a8
--- /dev/null
+++ b/Help/prop_tgt/CUDA_OPTIX_COMPILATION.rst
@@ -0,0 +1,14 @@
+CUDA_OPTIX_COMPILATION
+----------------------
+
+.. versionadded:: 3.27
+
+Compile CUDA sources to ``.optixir`` files instead of ``.obj`` files
+within :ref:`Object Libraries`.
+
+For example:
+
+.. code-block:: cmake
+
+ add_library(myoptix OBJECT a.cu b.cu)
+ set_property(TARGET myoptix PROPERTY CUDA_OPTIX_COMPILATION ON)
diff --git a/Help/release/dev/cuda-support-new-compile-modes.rst b/Help/release/dev/cuda-support-new-compile-modes.rst
new file mode 100644
index 0000000..2d24c16
--- /dev/null
+++ b/Help/release/dev/cuda-support-new-compile-modes.rst
@@ -0,0 +1,14 @@
+cuda-support-new-compile-modes
+------------------------------
+
+* A :prop_tgt:`CUDA_CUBIN_COMPILATION` target property was added to
+ :ref:`Object Libraries` to support compiling to ``.cubin`` files
+ instead of host object files. Currently only supported with NVIDIA.
+
+* A :prop_tgt:`CUDA_FATBIN_COMPILATION` target property was added to
+ :ref:`Object Libraries` to support compiling to ``.fatbin`` files
+ instead of host object files. Currently only supported with NVIDIA.
+
+* A :prop_tgt:`CUDA_OPTIX_COMPILATION` target property was added to
+ :ref:`Object Libraries` to support compiling to ``.optixir`` files
+ instead of host object files. Currently only supported with NVIDIA.
diff --git a/Help/variable/CMAKE_MAXIMUM_RECURSION_DEPTH.rst b/Help/variable/CMAKE_MAXIMUM_RECURSION_DEPTH.rst
index 59c60d3..b611967 100644
--- a/Help/variable/CMAKE_MAXIMUM_RECURSION_DEPTH.rst
+++ b/Help/variable/CMAKE_MAXIMUM_RECURSION_DEPTH.rst
@@ -33,3 +33,5 @@ Calling any of the following commands increases the recursion depth:
depth)
* Reading or writing variables that are being watched by a
:command:`variable_watch`
+
+See also the :envvar:`CMAKE_MAXIMUM_RECURSION_DEPTH` environment variable.
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index dea721e..e774088 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -134,7 +134,6 @@ include(CMakeCommonLanguageInclude)
# CMAKE_CUDA_CREATE_SHARED_LIBRARY
# CMAKE_CUDA_CREATE_SHARED_MODULE
# CMAKE_CUDA_COMPILE_WHOLE_COMPILATION
-# CMAKE_CUDA_COMPILE_PTX_COMPILATION
# CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
# CMAKE_CUDA_LINK_EXECUTABLE
diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
index cd978d5..bda1d71 100644
--- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
+++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
@@ -12,7 +12,6 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR)
FAIL_REGEX "switch .* is no longer supported" # GNU
FAIL_REGEX "unknown .*option" # Clang
FAIL_REGEX "optimization flag .* not supported" # Clang
- FAIL_REGEX "argument unused during compilation: .*" # Clang
FAIL_REGEX "unknown argument ignored" # Clang (cl)
FAIL_REGEX "ignoring unknown option" # MSVC, Intel
FAIL_REGEX "warning D9002" # MSVC, any lang
diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake
index 065b90a..cd89a55 100644
--- a/Modules/CheckCCompilerFlag.cmake
+++ b/Modules/CheckCCompilerFlag.cmake
@@ -45,7 +45,6 @@ following variables prior to calling ``check_c_compiler_flag()``
#]=======================================================================]
include_guard(GLOBAL)
-include(CheckCSourceCompiles)
include(Internal/CheckCompilerFlag)
macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT)
diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake
index b319d90..a6884f5 100644
--- a/Modules/CheckCXXCompilerFlag.cmake
+++ b/Modules/CheckCXXCompilerFlag.cmake
@@ -28,7 +28,6 @@ effect or even a specific one is beyond the scope of this module.
#]=======================================================================]
include_guard(GLOBAL)
-include(CheckCXXSourceCompiles)
include(Internal/CheckCompilerFlag)
macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
diff --git a/Modules/CheckFortranCompilerFlag.cmake b/Modules/CheckFortranCompilerFlag.cmake
index a7e544d..c3cd088 100644
--- a/Modules/CheckFortranCompilerFlag.cmake
+++ b/Modules/CheckFortranCompilerFlag.cmake
@@ -47,7 +47,6 @@ following variables prior to calling ``check_fortran_compiler_flag()``
#]=======================================================================]
include_guard(GLOBAL)
-include(CheckFortranSourceCompiles)
include(Internal/CheckCompilerFlag)
macro (CHECK_FORTRAN_COMPILER_FLAG _FLAG _RESULT)
diff --git a/Modules/CheckOBJCCompilerFlag.cmake b/Modules/CheckOBJCCompilerFlag.cmake
index b0b7a43..ceb7e17 100644
--- a/Modules/CheckOBJCCompilerFlag.cmake
+++ b/Modules/CheckOBJCCompilerFlag.cmake
@@ -47,7 +47,6 @@ following variables prior to calling ``check_objc_compiler_flag()``
#]=======================================================================]
include_guard(GLOBAL)
-include(CheckOBJCSourceCompiles)
include(Internal/CheckCompilerFlag)
macro (CHECK_OBJC_COMPILER_FLAG _FLAG _RESULT)
diff --git a/Modules/CheckOBJCXXCompilerFlag.cmake b/Modules/CheckOBJCXXCompilerFlag.cmake
index cead15b..47dacc2 100644
--- a/Modules/CheckOBJCXXCompilerFlag.cmake
+++ b/Modules/CheckOBJCXXCompilerFlag.cmake
@@ -47,7 +47,6 @@ following variables prior to calling ``check_objcxx_compiler_flag()``
#]=======================================================================]
include_guard(GLOBAL)
-include(CheckOBJCXXSourceCompiles)
include(Internal/CheckCompilerFlag)
macro (CHECK_OBJCXX_COMPILER_FLAG _FLAG _RESULT)
diff --git a/Modules/CheckStructHasMember.cmake b/Modules/CheckStructHasMember.cmake
index 55c7cf4..81ea9fd 100644
--- a/Modules/CheckStructHasMember.cmake
+++ b/Modules/CheckStructHasMember.cmake
@@ -48,8 +48,7 @@ Example:
#]=======================================================================]
include_guard(GLOBAL)
-include(CheckCSourceCompiles)
-include(CheckCXXSourceCompiles)
+include(CheckSourceCompiles)
macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
set(_INCLUDE_FILES)
@@ -75,9 +74,9 @@ int main()
")
if("${_lang}" STREQUAL "C")
- CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
+ CHECK_SOURCE_COMPILES(C "${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
elseif("${_lang}" STREQUAL "CXX")
- CHECK_CXX_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
+ CHECK_SOURCE_COMPILES(CXX "${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
else()
message(FATAL_ERROR "Unknown language:\n ${_lang}\nSupported languages: C, CXX.\n")
endif()
diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake
index bae0fbd..98f58e7 100644
--- a/Modules/Compiler/IAR-ASM.cmake
+++ b/Modules/Compiler/IAR-ASM.cmake
@@ -2,44 +2,74 @@
include(Compiler/IAR)
-cmake_policy(PUSH)
-cmake_policy(SET CMP0057 NEW) # if IN_LIST
-
-set(_CMAKE_IAR_ITOOLS "ARM" "RH850" "RL78" "RX" "RISC-V" "STM8")
-set(_CMAKE_IAR_XTOOLS "AVR" "MSP430" "V850" "8051")
+# Architecture specific
+if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM")
+ __compiler_iar_ilink(ASM)
+ __assembler_iar_deps("-y" 9)
+ set(_CMAKE_IAR_SILENCER_FLAG " -S")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
-set(_CMAKE_IAR_ASM_SILENT "RH850" "RL78" "RX" "RISC-V" "STM8")
-if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ASM_SILENT)
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX")
+ __compiler_iar_ilink(ASM)
+ __assembler_iar_deps("--dependencies=ns" 2.50.1)
set(_CMAKE_IAR_SILENCER_FLAG " --silent")
-else()
- set(_CMAKE_IAR_SILENCER_FLAG " -S")
-endif()
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
-string(APPEND CMAKE_ASM_FLAGS_INIT " ")
-string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r")
-string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
-string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG")
-string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850")
+ __compiler_iar_ilink(ASM)
+ __assembler_iar_deps("--dependencies=ns" 2)
+ set(_CMAKE_IAR_SILENCER_FLAG " --silent")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
-set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> ${_CMAKE_IAR_SILENCER_FLAG} <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78")
+ __compiler_iar_ilink(ASM)
+ __assembler_iar_deps("--dependencies=ns" 2)
+ set(_CMAKE_IAR_SILENCER_FLAG " --silent")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
-if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS)
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" MATCHES "(RISCV|RISC-V)")
__compiler_iar_ilink(ASM)
+ __assembler_iar_deps("--dependencies=ns" 1)
+ set(_CMAKE_IAR_SILENCER_FLAG " --silent")
set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_XTOOLS)
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR")
+ __compiler_iar_xlink(ASM)
+ __assembler_iar_deps("-y" 8)
+ set(_CMAKE_IAR_SILENCER_FLAG " -S")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;asm;msa)
+
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430")
__compiler_iar_xlink(ASM)
- # AVR=s90, MSP430=s43, V850=s85, 8051=s51
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;s43;s85;s51;asm;msa)
+ __assembler_iar_deps("-y" 8)
+ set(_CMAKE_IAR_SILENCER_FLAG " -S")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s43;asm;msa)
-else()
- message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.")
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850")
+ __compiler_iar_xlink(ASM)
+ set(_CMAKE_IAR_SILENCER_FLAG " -S")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s85;asm;msa)
+
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051")
+ __compiler_iar_xlink(ASM)
+ set(_CMAKE_IAR_SILENCER_FLAG " -S")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s51;asm;msa)
+
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8")
+ __compiler_iar_ilink(ASM)
+ __assembler_iar_deps("--dependencies=ns" 2)
+ set(_CMAKE_IAR_SILENCER_FLAG " --silent")
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
+else()
+ message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected. This should be automatic." )
endif()
-unset(_CMAKE_IAR_ITOOLS)
-unset(_CMAKE_IAR_XTOOLS)
-unset(_CMAKE_IAR_ASM_SILENT)
-unset(_CMAKE_IAR_SILENCER_FLAG)
+string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r")
+string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG")
+string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
-cmake_policy(POP)
+set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> ${_CMAKE_IAR_SILENCER_FLAG} <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
+
+unset(_CMAKE_IAR_SILENCER_FLAG)
diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake
index e75df59..0aca283 100644
--- a/Modules/Compiler/IAR.cmake
+++ b/Modules/Compiler/IAR.cmake
@@ -53,3 +53,9 @@ macro(__compiler_iar_xlink lang)
set(CMAKE_LIBRARY_PATH_FLAG "-I")
endmacro()
+
+macro(__assembler_iar_deps flag min_version)
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL ${min_version})
+ set(CMAKE_DEPFILE_FLAGS_ASM "${flag} <DEP_FILE>")
+ endif()
+endmacro()
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index 0823954..c839d1c 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -8,6 +8,11 @@ set(_CMAKE_COMPILE_AS_CUDA_FLAG "-x cu")
set(_CMAKE_CUDA_WHOLE_FLAG "-c")
set(_CMAKE_CUDA_RDC_FLAG "-rdc=true")
set(_CMAKE_CUDA_PTX_FLAG "-ptx")
+set(_CMAKE_CUDA_CUBIN_FLAG "-cubin")
+set(_CMAKE_CUDA_FATBIN_FLAG "-fatbin")
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.7.0")
+ set(_CMAKE_CUDA_OPTIX_FLAG "-optix-ir")
+endif()
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89)
# The -forward-unknown-to-host-compiler flag was only
diff --git a/Modules/FortranCInterface/CMakeLists.txt b/Modules/FortranCInterface/CMakeLists.txt
index 4bd7006..a0f1862 100644
--- a/Modules/FortranCInterface/CMakeLists.txt
+++ b/Modules/FortranCInterface/CMakeLists.txt
@@ -6,11 +6,11 @@ project(FortranCInterface C Fortran)
include(${FortranCInterface_BINARY_DIR}/Input.cmake OPTIONAL)
# Check if the C compiler supports '$' in identifiers.
-include(CheckCSourceCompiles)
-check_c_source_compiles("
-extern int dollar$(void);
-int main() { return 0; }
-" C_SUPPORTS_DOLLAR)
+include(CheckSourceCompiles)
+check_source_compiles(C
+"extern int dollar$(void);
+int main() { return 0; }"
+C_SUPPORTS_DOLLAR)
# List manglings of global symbol names to try.
set(global_symbols
diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake
index ea8616a..01a6e4f 100644
--- a/Modules/GenerateExportHeader.cmake
+++ b/Modules/GenerateExportHeader.cmake
@@ -198,19 +198,19 @@ that will be populated with the ``CXX_FLAGS`` required to enable visibility
support for the compiler/architecture in use.
#]=======================================================================]
-include(CheckCCompilerFlag)
-include(CheckCXXCompilerFlag)
+include(CheckCompilerFlag)
+include(CheckSourceCompiles)
# TODO: Install this macro separately?
macro(_check_cxx_compiler_attribute _ATTRIBUTE _RESULT)
- check_cxx_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; }
+ check_source_compiles(CXX "${_ATTRIBUTE} int somefunc() { return 0; }
int main() { return somefunc();}" ${_RESULT}
)
endmacro()
# TODO: Install this macro separately?
macro(_check_c_compiler_attribute _ATTRIBUTE _RESULT)
- check_c_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; }
+ check_source_compiles(C "${_ATTRIBUTE} int somefunc() { return 0; }
int main() { return somefunc();}" ${_RESULT}
)
endmacro()
@@ -226,7 +226,7 @@ macro(_test_compiler_hidden_visibility)
endif()
# Exclude XL here because it misinterprets -fvisibility=hidden even though
- # the check_cxx_compiler_flag passes
+ # the check_compiler_flag passes
if(NOT GCC_TOO_OLD
AND NOT _INTEL_TOO_OLD
AND NOT WIN32
@@ -235,12 +235,12 @@ macro(_test_compiler_hidden_visibility)
AND NOT CMAKE_CXX_COMPILER_ID MATCHES "^(PGI|NVHPC)$"
AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom)
if (CMAKE_CXX_COMPILER_LOADED)
- check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
- check_cxx_compiler_flag(-fvisibility-inlines-hidden
+ check_compiler_flag(CXX -fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
+ check_compiler_flag(CXX -fvisibility-inlines-hidden
COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
else()
- check_c_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
- check_c_compiler_flag(-fvisibility-inlines-hidden
+ check_compiler_flag(C -fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
+ check_compiler_flag(C -fvisibility-inlines-hidden
COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
endif()
endif()
diff --git a/Modules/Internal/CMakeTryCompilerOrLinkerFlag.cmake b/Modules/Internal/CMakeTryCompilerOrLinkerFlag.cmake
index ff8908b..b671b4a 100644
--- a/Modules/Internal/CMakeTryCompilerOrLinkerFlag.cmake
+++ b/Modules/Internal/CMakeTryCompilerOrLinkerFlag.cmake
@@ -69,6 +69,7 @@ function(CMAKE_TRY_COMPILER_OR_LINKER_FLAG lang flag result)
set (CCCF_COMMAND_PATTERN "<FLAG> -o <OUTPUT> <SOURCE>")
endif()
+ list (APPEND CCCF_FAIL_REGEX "argument unused during compilation") # clang
if (check_lang STREQUAL "C")
list(APPEND CCCF_FAIL_REGEX
"command line option .* is valid for .* but not for C") # GNU
diff --git a/Modules/Internal/CheckFlagCommonConfig.cmake b/Modules/Internal/CheckFlagCommonConfig.cmake
index 744f1f1..8c5703d 100644
--- a/Modules/Internal/CheckFlagCommonConfig.cmake
+++ b/Modules/Internal/CheckFlagCommonConfig.cmake
@@ -23,26 +23,30 @@ macro(CMAKE_CHECK_FLAG_COMMON_INIT _FUNC _LANG _SRC _PATTERNS)
FAIL_REGEX "-Werror=.* argument .* is not valid for C\\+\\+")
elseif("${_LANG}" STREQUAL "CUDA")
set(${_SRC} "__host__ int main() { return 0; }")
- set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+") # Host GNU
+ set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" # Host GNU
+ FAIL_REGEX "argument unused during compilation: .*") # Clang
elseif("${_LANG}" STREQUAL "Fortran")
set(${_SRC} " program test\n stop\n end program")
set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Fortran")
elseif("${_LANG}" STREQUAL "HIP")
set(${_SRC} "__host__ int main() { return 0; }")
+ set(${_PATTERNS} FAIL_REGEX "argument unused during compilation: .*") # Clang
elseif("${_LANG}" STREQUAL "OBJC")
set(${_SRC} [=[
#ifndef __OBJC__
# error "Not an Objective-C compiler"
#endif
int main(void) { return 0; }]=])
- set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C") # GNU
+ set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C" # GNU
+ FAIL_REGEX "argument unused during compilation: .*") # Clang
elseif("${_LANG}" STREQUAL "OBJCXX")
set(${_SRC} [=[
#ifndef __OBJC__
# error "Not an Objective-C++ compiler"
#endif
int main(void) { return 0; }]=])
- set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C\\+\\+") # GNU
+ set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C\\+\\+" # GNU
+ FAIL_REGEX "argument unused during compilation: .*") # Clang
elseif("${_LANG}" STREQUAL "ISPC")
set(${_SRC} "float func(uniform int32, float a) { return a / 2.25; }")
elseif("${_LANG}" STREQUAL "Swift")
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 163dab3..33514ba 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -11,20 +11,6 @@ endif()
include(CheckIncludeFile)
-if(NOT CMake_DEFAULT_RECURSION_LIMIT)
- if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST})
- set(CMake_DEFAULT_RECURSION_LIMIT 100)
- elseif(MINGW OR MSYS)
- set(CMake_DEFAULT_RECURSION_LIMIT 400)
- elseif(WIN32 AND CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "ARM64")
- set(CMake_DEFAULT_RECURSION_LIMIT 400)
- elseif(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
- set(CMake_DEFAULT_RECURSION_LIMIT 600)
- else()
- set(CMake_DEFAULT_RECURSION_LIMIT 1000)
- endif()
-endif()
-
if(APPLE)
set(CMake_USE_MACH_PARSER 1)
endif()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f465806..cf6043a 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 26)
-set(CMake_VERSION_PATCH 20230313)
+set(CMake_VERSION_PATCH 20230316)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 90f3de0..3f19a11 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -23,7 +23,7 @@
#cmakedefine CMake_USE_MACH_PARSER
#cmakedefine CMake_USE_XCOFF_PARSER
#cmakedefine CMAKE_USE_WMAKE
-#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
+#cmakedefine CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
#define CMAKE_DOC_DIR "/@CMAKE_DOC_DIR@"
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 4024dff..c228cde 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -977,6 +977,21 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
}
+ // Limit package nesting depth well below the recursion depth limit because
+ // find_package nesting uses more stack space than normal recursion.
+ {
+ static std::size_t const findPackageDepthMinMax = 100;
+ std::size_t const findPackageDepthMax = std::max(
+ this->Makefile->GetRecursionDepthLimit() / 2, findPackageDepthMinMax);
+ std::size_t const findPackageDepth =
+ this->Makefile->FindPackageRootPathStack.size() + 1;
+ if (findPackageDepth > findPackageDepthMax) {
+ this->SetError(cmStrCat("maximum nesting depth of ", findPackageDepthMax,
+ " exceeded."));
+ return false;
+ }
+ }
+
this->PushFindPackageRootPathStack();
this->SetModuleVariables(components, componentVarDefs);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 54cd8ba..4cfa1d7 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -3,6 +3,7 @@
#include "cmGeneratorTarget.h"
#include <algorithm>
+#include <array>
#include <cassert>
#include <cerrno>
#include <cstddef>
@@ -1011,12 +1012,27 @@ const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
const char* cmGeneratorTarget::GetCustomObjectExtension() const
{
- static std::string extension;
- const bool has_ptx_extension =
- this->GetPropertyAsBool("CUDA_PTX_COMPILATION");
- if (has_ptx_extension) {
- extension = ".ptx";
- return extension.c_str();
+ struct compiler_mode
+ {
+ std::string variable;
+ std::string extension;
+ };
+ static std::array<compiler_mode, 4> const modes{
+ { { "CUDA_PTX_COMPILATION", ".ptx" },
+ { "CUDA_CUBIN_COMPILATION", ".cubin" },
+ { "CUDA_FATBIN_COMPILATION", ".fatbin" },
+ { "CUDA_OPTIX_COMPILATION", ".optixir" } }
+ };
+
+ std::string const& compiler =
+ this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
+ if (!compiler.empty()) {
+ for (const auto& m : modes) {
+ const bool has_extension = this->GetPropertyAsBool(m.variable);
+ if (has_extension) {
+ return m.extension.c_str();
+ }
+ }
}
return nullptr;
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 72eed69..7ed68d6 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -110,8 +110,6 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
this->ConfigureDoneCMP0026AndCMP0024 = false;
this->FirstTimeProgress = 0.0f;
- this->RecursionDepth = 0;
-
cm->GetState()->SetIsGeneratorMultiConfig(false);
cm->GetState()->SetMinGWMake(false);
cm->GetState()->SetMSYSShell(false);
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 66ab752..7de8215 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -586,7 +586,7 @@ public:
std::string MakeSilentFlag;
- int RecursionDepth;
+ size_t RecursionDepth = 0;
virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const
{
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 3fcc7f7..fc82c14 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -67,6 +67,24 @@
# include "cmVariableWatch.h"
#endif
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+// Select a recursion limit that fits within the stack size.
+// See stack size flags in '../CompileFlags.cmake'.
+#ifndef CMake_DEFAULT_RECURSION_LIMIT
+# if __has_feature(address_sanitizer)
+# define CMake_DEFAULT_RECURSION_LIMIT 400
+# elif defined(_MSC_VER) && defined(_DEBUG)
+# define CMake_DEFAULT_RECURSION_LIMIT 600
+# elif defined(__ibmxl__) && defined(__linux)
+# define CMake_DEFAULT_RECURSION_LIMIT 600
+# else
+# define CMake_DEFAULT_RECURSION_LIMIT 1000
+# endif
+#endif
+
class cmMessenger;
cmDirectoryId::cmDirectoryId(std::string s)
@@ -99,7 +117,6 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
this->StateSnapshot =
this->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
this->StateSnapshot);
- this->RecursionDepth = 0;
// Enter a policy level for this directory.
this->PushPolicy();
@@ -454,18 +471,10 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
static_cast<void>(stack_manager);
// Check for maximum recursion depth.
- int depth = CMake_DEFAULT_RECURSION_LIMIT;
- cmValue depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
- if (depthStr) {
- std::istringstream s(*depthStr);
- int d;
- if (s >> d) {
- depth = d;
- }
- }
- if (this->RecursionDepth > depth) {
+ size_t depthLimit = this->GetRecursionDepthLimit();
+ if (this->RecursionDepth > depthLimit) {
std::ostringstream e;
- e << "Maximum recursion depth of " << depth << " exceeded";
+ e << "Maximum recursion depth of " << depthLimit << " exceeded";
this->IssueMessage(MessageType::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccurred();
return false;
@@ -2865,12 +2874,31 @@ bool cmMakefile::IsProjectFile(const char* filename) const
!cmSystemTools::IsSubDirectory(filename, "/CMakeFiles"));
}
-int cmMakefile::GetRecursionDepth() const
+size_t cmMakefile::GetRecursionDepthLimit() const
+{
+ size_t depth = CMake_DEFAULT_RECURSION_LIMIT;
+ if (cmValue depthStr =
+ this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH")) {
+ unsigned long depthUL;
+ if (cmStrToULong(depthStr.GetCStr(), &depthUL)) {
+ depth = depthUL;
+ }
+ } else if (cm::optional<std::string> depthEnv =
+ cmSystemTools::GetEnvVar("CMAKE_MAXIMUM_RECURSION_DEPTH")) {
+ unsigned long depthUL;
+ if (cmStrToULong(*depthEnv, &depthUL)) {
+ depth = depthUL;
+ }
+ }
+ return depth;
+}
+
+size_t cmMakefile::GetRecursionDepth() const
{
return this->RecursionDepth;
}
-void cmMakefile::SetRecursionDepth(int recursionDepth)
+void cmMakefile::SetRecursionDepth(size_t recursionDepth)
{
this->RecursionDepth = recursionDepth;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 6f04937..a43ff41 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1023,8 +1023,10 @@ public:
const char* sourceFilename) const;
bool IsProjectFile(const char* filename) const;
- int GetRecursionDepth() const;
- void SetRecursionDepth(int recursionDepth);
+ size_t GetRecursionDepthLimit() const;
+
+ size_t GetRecursionDepth() const;
+ void SetRecursionDepth(size_t recursionDepth);
std::string NewDeferId() const;
bool DeferCall(std::string id, std::string fileName, cmListFileFunction lff);
@@ -1090,7 +1092,7 @@ protected:
private:
cmStateSnapshot StateSnapshot;
cmListFileBacktrace Backtrace;
- int RecursionDepth;
+ size_t RecursionDepth = 0;
struct DeferCommand
{
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index e217dd9..2ead739 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -3,6 +3,7 @@
#include "cmMakefileTargetGenerator.h"
#include <algorithm>
+#include <array>
#include <cassert>
#include <cstdio>
#include <iterator>
@@ -977,11 +978,23 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
}
- if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
- const std::string& ptxFlag =
- this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
- cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
- } else {
+
+ static std::array<cm::string_view, 4> const compileModes{
+ { "PTX"_s, "CUBIN"_s, "FATBIN"_s, "OPTIX"_s }
+ };
+ bool useNormalCompileMode = true;
+ for (cm::string_view mode : compileModes) {
+ auto propName = cmStrCat("CUDA_", mode, "_COMPILATION");
+ auto defName = cmStrCat("_CMAKE_CUDA_", mode, "_FLAG");
+ if (this->GeneratorTarget->GetPropertyAsBool(propName)) {
+ const std::string& flag =
+ this->Makefile->GetRequiredDefinition(defName);
+ cudaCompileMode = cmStrCat(cudaCompileMode, flag);
+ useNormalCompileMode = false;
+ break;
+ }
+ }
+ if (useNormalCompileMode) {
const std::string& wholeFlag =
this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 8663f46..dc56142 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -3,6 +3,7 @@
#include "cmNinjaTargetGenerator.h"
#include <algorithm>
+#include <array>
#include <cassert>
#include <functional>
#include <iterator>
@@ -859,11 +860,22 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
}
- if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
- const std::string& ptxFlag =
- this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
- cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
- } else {
+ static std::array<cm::string_view, 4> const compileModes{
+ { "PTX"_s, "CUBIN"_s, "FATBIN"_s, "OPTIX"_s }
+ };
+ bool useNormalCompileMode = true;
+ for (cm::string_view mode : compileModes) {
+ auto propName = cmStrCat("CUDA_", mode, "_COMPILATION");
+ auto defName = cmStrCat("_CMAKE_CUDA_", mode, "_FLAG");
+ if (this->GeneratorTarget->GetPropertyAsBool(propName)) {
+ const std::string& flag =
+ this->Makefile->GetRequiredDefinition(defName);
+ cudaCompileMode = cmStrCat(cudaCompileMode, flag);
+ useNormalCompileMode = false;
+ break;
+ }
+ }
+ if (useNormalCompileMode) {
const std::string& wholeFlag =
this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
@@ -1789,11 +1801,22 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
}
- if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
- const std::string& ptxFlag =
- this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
- cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
- } else {
+ static std::array<cm::string_view, 4> const compileModes{
+ { "PTX"_s, "CUBIN"_s, "FATBIN"_s, "OPTIX"_s }
+ };
+ bool useNormalCompileMode = true;
+ for (cm::string_view mode : compileModes) {
+ auto propName = cmStrCat("CUDA_", mode, "_COMPILATION");
+ auto defName = cmStrCat("_CMAKE_CUDA_", mode, "_FLAG");
+ if (this->GeneratorTarget->GetPropertyAsBool(propName)) {
+ const std::string& flag =
+ this->Makefile->GetRequiredDefinition(defName);
+ cudaCompileMode = cmStrCat(cudaCompileMode, flag);
+ useNormalCompileMode = false;
+ break;
+ }
+ }
+ if (useNormalCompileMode) {
const std::string& wholeFlag =
this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 5ff7009..f48330d 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -33,6 +33,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
, VersionDirective("^.. version(added|changed)::[ \t]*(.*)$")
, ModuleRST(R"(^#\[(=*)\[\.rst:$)")
, CMakeRole("(:cmake)?:("
+ "cref|"
"command|cpack_gen|generator|genex|"
"variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ec87271..f06e26b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1775,6 +1775,9 @@ MAKE_PROP(COMPILE_FEATURES);
MAKE_PROP(COMPILE_OPTIONS);
MAKE_PROP(PRECOMPILE_HEADERS);
MAKE_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
+MAKE_PROP(CUDA_CUBIN_COMPILATION);
+MAKE_PROP(CUDA_FATBIN_COMPILATION);
+MAKE_PROP(CUDA_OPTIX_COMPILATION);
MAKE_PROP(CUDA_PTX_COMPILATION);
MAKE_PROP(EXPORT_NAME);
MAKE_PROP(IMPORTED);
@@ -1910,14 +1913,38 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
value ? value
: std::string{})) { // NOLINT(bugprone-branch-clone)
/* error was reported by check method */
- } else if (prop == propCUDA_PTX_COMPILATION &&
- this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT "
- "targets (\""
- << this->impl->Name << "\")\n";
- this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return;
+ } else if (prop == propCUDA_CUBIN_COMPILATION ||
+ prop == propCUDA_FATBIN_COMPILATION ||
+ prop == propCUDA_OPTIX_COMPILATION ||
+ prop == propCUDA_PTX_COMPILATION) {
+ auto const& compiler =
+ this->impl->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
+ auto const& compilerVersion =
+ this->impl->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_VERSION");
+ if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ auto e =
+ cmStrCat(prop, " property can only be applied to OBJECT targets(",
+ this->impl->Name, ")\n");
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+ return;
+ }
+ const bool flag_found =
+ (prop == propCUDA_PTX_COMPILATION &&
+ this->impl->Makefile->GetDefinition("_CMAKE_CUDA_PTX_FLAG")) ||
+ (prop == propCUDA_CUBIN_COMPILATION &&
+ this->impl->Makefile->GetDefinition("_CMAKE_CUDA_CUBIN_FLAG")) ||
+ (prop == propCUDA_FATBIN_COMPILATION &&
+ this->impl->Makefile->GetDefinition("_CMAKE_CUDA_FATBIN_FLAG")) ||
+ (prop == propCUDA_OPTIX_COMPILATION &&
+ this->impl->Makefile->GetDefinition("_CMAKE_CUDA_OPTIX_FLAG"));
+ if (flag_found) {
+ this->impl->Properties.SetProperty(prop, value);
+ } else {
+ auto e = cmStrCat(prop, " property is not supported by ", compiler,
+ " compiler version ", compilerVersion, ".");
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+ return;
+ }
} else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) {
if (this->GetProperty("PRECOMPILE_HEADERS")) {
std::ostringstream e;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index ef0fcf3..8926f9e 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3597,13 +3597,13 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
}
- bool notPtx = true;
+ bool notPtxLike = true;
if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
cudaOptions.AddFlag("NvccCompilation", "ptx");
// We drop the %(Extension) component as CMake expects all PTX files
// to not have the source file extension at all
cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx");
- notPtx = false;
+ notPtxLike = false;
if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
cudaVersion, "9.0") &&
@@ -3618,9 +3618,24 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
"%(BaseCommandLineTemplate) [CompileOut] [FastMath] "
"[Defines] \"%(FullPath)\"");
}
- }
-
- if (notPtx &&
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_CUBIN_COMPILATION")) {
+ cudaOptions.AddFlag("NvccCompilation", "cubin");
+ cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).cubin");
+ notPtxLike = false;
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_FATBIN_COMPILATION")) {
+ cudaOptions.AddFlag("NvccCompilation", "fatbin");
+ cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).fatbin");
+ notPtxLike = false;
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_OPTIX_COMPILATION")) {
+ cudaOptions.AddFlag("NvccCompilation", "optix-ir");
+ cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).optixir");
+ notPtxLike = false;
+ }
+
+ if (notPtxLike &&
cmSystemTools::VersionCompareGreaterEq(
"8.0", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
// Explicitly state that we want this file to be treated as a
diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect
index 483e220..424b7d4 100644
--- a/Tests/CMakeLib/testRST.expect
+++ b/Tests/CMakeLib/testRST.expect
@@ -26,10 +26,15 @@ Generator expression ``$<SOME_GENEX:...>`` with brackets and parameter.
Generator expression ``some genex`` with space and target.
Generator expression ``$<SOME_GENEX>`` with brackets, space, and target.
Generator expression ``$<SOME_GENEX:...>`` with brackets, parameter, space, and target.
-Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
+Inline cref ``Link Dest``.
+Inline cref ``Link_Dest_<Placeholder>``.
+Inline cref ``Link Text``.
+Inline cref ``Link_Text_<Placeholder>``.
+Inline link Link Dest.
Inline link Link Text.
Inline link Link Text <With \-escaped Brackets>.
Inline literal ``__`` followed by inline link Link Text.
+Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
First TOC entry.
diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst
index c23b69a..3a38407 100644
--- a/Tests/CMakeLib/testRST.rst
+++ b/Tests/CMakeLib/testRST.rst
@@ -33,10 +33,15 @@ Generator expression :genex:`$<SOME_GENEX:...>` with brackets and parameter.
Generator expression :genex:`some genex <SOME_GENEX>` with space and target.
Generator expression :genex:`$<SOME_GENEX> <SOME_GENEX>` with brackets, space, and target.
Generator expression :genex:`$<SOME_GENEX:...> <SOME_GENEX>` with brackets, parameter, space, and target.
-Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
+Inline cref :cref:`Link Dest`.
+Inline cref :cref:`Link_Dest_<Placeholder>`.
+Inline cref :cref:`Link Text <ExternalDest>`.
+Inline cref :cref:`Link_Text_<Placeholder> <ExternalDest>`.
+Inline link `Link Dest`_.
Inline link `Link Text <ExternalDest>`_.
Inline link `Link Text \<With \\-escaped Brackets\> <ExternalDest>`_.
Inline literal ``__`` followed by inline link `Link Text <InternalDest_>`_.
+Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
.. |not replaced| replace:: not replaced through toctree
.. |not replaced in literal| replace:: replaced in parsed literal
diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt
index db08076..aa25c4c 100644
--- a/Tests/CudaOnly/CMakeLists.txt
+++ b/Tests/CudaOnly/CMakeLists.txt
@@ -27,6 +27,9 @@ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang")
# Only NVCC defines __CUDACC_DEBUG__ when compiling in debug mode.
add_cuda_test_macro(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag)
+ add_cuda_test_macro(CudaOnly.CUBIN CudaOnlyCUBIN)
+ add_cuda_test_macro(CudaOnly.Fatbin CudaOnlyFatbin)
+ add_cuda_test_macro(CudaOnly.OptixIR CudaOnlyOptixIR)
endif()
add_cuda_test_macro(CudaOnly.DeviceLTO CudaOnlyDeviceLTO)
diff --git a/Tests/CudaOnly/CUBIN/CMakeLists.txt b/Tests/CudaOnly/CUBIN/CMakeLists.txt
new file mode 100644
index 0000000..464714b
--- /dev/null
+++ b/Tests/CudaOnly/CUBIN/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 3.18)
+project(CudaCUBIN LANGUAGES CUDA)
+
+
+set(CMAKE_CUDA_ARCHITECTURES all-major)
+
+add_library(CudaCUBIN OBJECT kernelA.cu kernelB.cu kernelC.cu)
+set_property(TARGET CudaCUBIN PROPERTY CUDA_CUBIN_COMPILATION ON)
+set_property(TARGET CudaCUBIN PROPERTY CUDA_ARCHITECTURES native)
+
+add_executable(CudaOnlyCUBIN main.cu)
+target_compile_features(CudaOnlyCUBIN PRIVATE cuda_std_11)
+target_compile_definitions(CudaOnlyCUBIN PRIVATE "CUBIN_FILE_PATHS=\"$<JOIN:$<TARGET_OBJECTS:CudaCUBIN>,~_~>\"")
+
+find_package(CUDAToolkit REQUIRED)
+target_link_libraries(CudaOnlyCUBIN PRIVATE CUDA::cuda_driver)
+
+if(APPLE)
+ # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+ set_property(TARGET CudaOnlyCUBIN PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()
diff --git a/Tests/CudaOnly/CUBIN/kernelA.cu b/Tests/CudaOnly/CUBIN/kernelA.cu
new file mode 100644
index 0000000..fbe0d26
--- /dev/null
+++ b/Tests/CudaOnly/CUBIN/kernelA.cu
@@ -0,0 +1,7 @@
+
+__global__ void kernelA(float* r, float* x, float* y, float* z, int size)
+{
+ for (int i = threadIdx.x; i < size; i += blockDim.x) {
+ r[i] = x[i] * y[i] + z[i];
+ }
+}
diff --git a/Tests/CudaOnly/CUBIN/kernelB.cu b/Tests/CudaOnly/CUBIN/kernelB.cu
new file mode 100644
index 0000000..7478253
--- /dev/null
+++ b/Tests/CudaOnly/CUBIN/kernelB.cu
@@ -0,0 +1,7 @@
+
+__global__ void kernelB(float* r, float* x, float* y, float* z, int size)
+{
+ for (int i = threadIdx.x; i < size; i += blockDim.x) {
+ r[i] = x[i] * y[i] + z[i];
+ }
+}
diff --git a/Tests/CudaOnly/CUBIN/kernelC.cu b/Tests/CudaOnly/CUBIN/kernelC.cu
new file mode 100644
index 0000000..5f8a0ce
--- /dev/null
+++ b/Tests/CudaOnly/CUBIN/kernelC.cu
@@ -0,0 +1,7 @@
+
+__global__ void kernelC(float* r, float* x, float* y, float* z, int size)
+{
+ for (int i = threadIdx.x; i < size; i += blockDim.x) {
+ r[i] = x[i] * y[i] + z[i];
+ }
+}
diff --git a/Tests/CudaOnly/CUBIN/main.cu b/Tests/CudaOnly/CUBIN/main.cu
new file mode 100644
index 0000000..da5249c
--- /dev/null
+++ b/Tests/CudaOnly/CUBIN/main.cu
@@ -0,0 +1,56 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <cuda.h>
+
+#define GENERATED_HEADER(x) GENERATED_HEADER1(x)
+#define GENERATED_HEADER1(x) <x>
+
+static std::string input_paths = { CUBIN_FILE_PATHS };
+
+int main()
+{
+ const std::string delimiter = "~_~";
+ input_paths += delimiter;
+
+ size_t end = 0;
+ size_t previous_end = 0;
+ std::vector<std::string> actual_paths;
+ while ((end = input_paths.find(delimiter, previous_end)) !=
+ std::string::npos) {
+ actual_paths.emplace_back(
+ input_paths.substr(previous_end, end - previous_end));
+ previous_end = end + 3;
+ }
+
+ cuInit(0);
+ int count = 0;
+ cuDeviceGetCount(&count);
+ if (count == 0) {
+ std::cerr << "No CUDA devices found\n";
+ return 1;
+ }
+
+ CUdevice device;
+ cuDeviceGet(&device, 0);
+
+ CUcontext context;
+ cuCtxCreate(&context, 0, device);
+
+ CUmodule module;
+ for (auto p : actual_paths) {
+ if (p.find(".cubin") == std::string::npos) {
+ std::cout << p << " Doesn't have the .cubin suffix" << p << std::endl;
+ return 1;
+ }
+ std::cout << "trying to load cubin: " << p << std::endl;
+ CUresult result = cuModuleLoad(&module, p.c_str());
+ std::cout << "module pointer: " << module << '\n';
+ if (result != CUDA_SUCCESS || module == nullptr) {
+ std::cerr << "Failed to load the embedded cubin with error: "
+ << static_cast<unsigned int>(result) << '\n';
+ return 1;
+ }
+ }
+}
diff --git a/Tests/CudaOnly/Fatbin/CMakeLists.txt b/Tests/CudaOnly/Fatbin/CMakeLists.txt
new file mode 100644
index 0000000..db0dc22
--- /dev/null
+++ b/Tests/CudaOnly/Fatbin/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.18)
+project(CudaFATBIN LANGUAGES CUDA)
+
+
+set(CMAKE_CUDA_ARCHITECTURES all-major)
+
+add_library(CudaFATBIN OBJECT
+${CMAKE_CURRENT_SOURCE_DIR}/../CUBIN/kernelA.cu
+${CMAKE_CURRENT_SOURCE_DIR}/../CUBIN/kernelB.cu
+${CMAKE_CURRENT_SOURCE_DIR}/../CUBIN/kernelC.cu)
+
+set_property(TARGET CudaFATBIN PROPERTY CUDA_FATBIN_COMPILATION ON)
+
+# Will use `cuModuleLoadFatBinary` to load the fatbinaries
+add_executable(CudaOnlyFatbin main.cu)
+target_compile_features(CudaOnlyFatbin PRIVATE cuda_std_11)
+target_compile_definitions(CudaOnlyFatbin PRIVATE "FATBIN_FILE_PATHS=\"$<JOIN:$<TARGET_OBJECTS:CudaFATBIN>,~_~>\"")
+
+find_package(CUDAToolkit REQUIRED)
+target_link_libraries(CudaOnlyFatbin PRIVATE CUDA::cuda_driver)
+
+if(APPLE)
+ # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+ set_property(TARGET CudaOnlyFatbin PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()
diff --git a/Tests/CudaOnly/Fatbin/main.cu b/Tests/CudaOnly/Fatbin/main.cu
new file mode 100644
index 0000000..903feee
--- /dev/null
+++ b/Tests/CudaOnly/Fatbin/main.cu
@@ -0,0 +1,56 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <cuda.h>
+
+#define GENERATED_HEADER(x) GENERATED_HEADER1(x)
+#define GENERATED_HEADER1(x) <x>
+
+static std::string input_paths = { FATBIN_FILE_PATHS };
+
+int main()
+{
+ const std::string delimiter = "~_~";
+ input_paths += delimiter;
+
+ size_t end = 0;
+ size_t previous_end = 0;
+ std::vector<std::string> actual_paths;
+ while ((end = input_paths.find(delimiter, previous_end)) !=
+ std::string::npos) {
+ actual_paths.emplace_back(
+ input_paths.substr(previous_end, end - previous_end));
+ previous_end = end + 3;
+ }
+
+ cuInit(0);
+ int count = 0;
+ cuDeviceGetCount(&count);
+ if (count == 0) {
+ std::cerr << "No CUDA devices found\n";
+ return 1;
+ }
+
+ CUdevice device;
+ cuDeviceGet(&device, 0);
+
+ CUcontext context;
+ cuCtxCreate(&context, 0, device);
+
+ CUmodule module;
+ for (auto p : actual_paths) {
+ if (p.find(".fatbin") == std::string::npos) {
+ std::cout << p << " Doesn't have the .fatbin suffix" << p << std::endl;
+ return 1;
+ }
+ std::cout << "trying to load fatbin: " << p << std::endl;
+ CUresult result = cuModuleLoad(&module, p.c_str());
+ std::cout << "module pointer: " << module << '\n';
+ if (result != CUDA_SUCCESS || module == nullptr) {
+ std::cerr << "Failed to load the embedded fatbin with error: "
+ << static_cast<unsigned int>(result) << '\n';
+ return 1;
+ }
+ }
+}
diff --git a/Tests/CudaOnly/OptixIR/CMakeLists.txt b/Tests/CudaOnly/OptixIR/CMakeLists.txt
new file mode 100644
index 0000000..afeabda
--- /dev/null
+++ b/Tests/CudaOnly/OptixIR/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.18)
+project(CudaOptix LANGUAGES CUDA)
+
+
+set(CMAKE_CUDA_ARCHITECTURES all-major)
+
+add_library(CudaOptix OBJECT
+ ${CMAKE_CURRENT_SOURCE_DIR}/../CUBIN/kernelA.cu
+ ${CMAKE_CURRENT_SOURCE_DIR}/../CUBIN/kernelB.cu
+ ${CMAKE_CURRENT_SOURCE_DIR}/../CUBIN/kernelC.cu)
+
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.7.0")
+ set_property(TARGET CudaOptix PROPERTY CUDA_OPTIX_COMPILATION ON)
+endif()
+
+set_property(TARGET CudaOptix PROPERTY CUDA_ARCHITECTURES native)
+
+add_executable(CudaOnlyOptixIR main.cu)
+target_compile_features(CudaOnlyOptixIR PRIVATE cuda_std_11)
+
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.7.0")
+ target_compile_definitions(CudaOnlyOptixIR PRIVATE "OPTIX_FILE_PATHS=\"$<JOIN:$<TARGET_OBJECTS:CudaOptix>,~_~>\"")
+else()
+ target_compile_definitions(CudaOnlyOptixIR PRIVATE "OPTIX_FILE_PATHS=\"NO_OPTIX_SUPPORT\"")
+endif()
+
+find_package(CUDAToolkit REQUIRED)
+target_link_libraries(CudaOnlyOptixIR PRIVATE CUDA::cuda_driver)
+
+if(APPLE)
+ # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+ set_property(TARGET CudaOnlyOptixIR PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()
diff --git a/Tests/CudaOnly/OptixIR/main.cu b/Tests/CudaOnly/OptixIR/main.cu
new file mode 100644
index 0000000..c79829b
--- /dev/null
+++ b/Tests/CudaOnly/OptixIR/main.cu
@@ -0,0 +1,53 @@
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <cuda.h>
+
+#define GENERATED_HEADER(x) GENERATED_HEADER1(x)
+#define GENERATED_HEADER1(x) <x>
+
+static std::string input_paths = { OPTIX_FILE_PATHS };
+
+int main()
+{
+ if (input_paths == "NO_OPTIX_SUPPORT") {
+ return 0;
+ }
+
+ const std::string delimiter = "~_~";
+ input_paths += delimiter;
+
+ size_t end = 0;
+ size_t previous_end = 0;
+ std::vector<std::string> actual_paths;
+ while ((end = input_paths.find(delimiter, previous_end)) !=
+ std::string::npos) {
+ actual_paths.emplace_back(
+ input_paths.substr(previous_end, end - previous_end));
+ previous_end = end + 3;
+ }
+
+ if (actual_paths.empty()) {
+ std::cerr << "Failed to parse OPTIX_FILE_PATHS" << std::endl;
+ return 1;
+ }
+
+ const std::uint32_t optix_magic_value = 0x7f4e43ed;
+ for (auto p : actual_paths) {
+ if (p.find(".optixir") == std::string::npos) {
+ std::cout << p << " Doesn't have the .optixir suffix" << p << std::endl;
+ return 1;
+ }
+ std::ifstream input(p, std::ios::binary);
+ std::uint32_t value;
+ input.read(reinterpret_cast<char*>(&value), sizeof(value));
+ if (value != optix_magic_value) {
+ std::cerr << p << " Doesn't look like an optix-ir file" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in
index 61be40b..a652efc 100644
--- a/Tests/EnforceConfig.cmake.in
+++ b/Tests/EnforceConfig.cmake.in
@@ -35,5 +35,8 @@ unset(ENV{CMAKE_GENERATOR_PLATFORM})
unset(ENV{CMAKE_GENERATOR_TOOLSET})
unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS})
+# Verify that our module implementations do not recurse too much.
+set(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH} 100)
+
@TEST_HOME_ENV_CODE@
@TEST_WARN_VS_CODE@
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake
index 276158c..64a961e 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake
@@ -18,6 +18,15 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_C_SIMULATE_ID}"
if(NOT SHOULD_WORK)
message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-x c' check failed")
endif()
+
+ block()
+ # Test tolerating a flag that is not used when driving the linker.
+ string(APPEND CMAKE_C_FLAGS " -nostdinc")
+ check_compiler_flag(C "-x c" SHOULD_WORK_NOSTDINC)
+ if(NOT SHOULD_WORK_NOSTDINC)
+ message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-x c -nostdinc' check failed")
+ endif()
+ endblock()
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "GNU") # LCC C compiler silently ignore -frtti instead of failing, so skip it here.
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake
index dec31ec..0026a2a 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake
@@ -18,6 +18,15 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_CXX_SIMULATE_
if(NOT SHOULD_WORK)
message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed")
endif()
+
+ block()
+ # Test tolerating a flag that is not used when driving the linker.
+ string(APPEND CMAKE_CXX_FLAGS " -nostdinc++")
+ check_compiler_flag(CXX "-x c++" SHOULD_WORK_NOSTDINCXX)
+ if(NOT SHOULD_WORK_NOSTDINCXX)
+ message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++ -nostdinc++' check failed")
+ endif()
+ endblock()
endif()
if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
diff --git a/Tests/RunCMake/MaxRecursionDepth/RunCMakeTest.cmake b/Tests/RunCMake/MaxRecursionDepth/RunCMakeTest.cmake
index c5a859d..fdf418f 100644
--- a/Tests/RunCMake/MaxRecursionDepth/RunCMakeTest.cmake
+++ b/Tests/RunCMake/MaxRecursionDepth/RunCMakeTest.cmake
@@ -1,26 +1,42 @@
include(RunCMake)
include(RunCTest)
-function(run_cmake_recursive name)
- set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
- run_cmake(${name}-default)
- unset(RunCMake_TEST_OPTIONS)
- set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
- run_cmake(${name}-var)
- unset(RunCMake_TEST_OPTIONS)
- set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a)
- run_cmake(${name}-invalid-var)
- unset(RunCMake_TEST_OPTIONS)
+# Isolate this test from the caller's environment.
+unset(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH})
+function(run_cmake_recursive name)
+ run_cmake_with_options(${name}-default "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
run_cmake_command(${name}-default-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
+
+ set(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH} 5) # overridden, not used
+ run_cmake_with_options(${name}-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
+ run_cmake_with_options(${name}-invalid-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a)
run_cmake_command(${name}-var-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10 -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
run_cmake_command(${name}-invalid-var-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
+
+ set(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH} 10)
+ run_cmake_with_options(${name}-env "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
+ run_cmake_command(${name}-env-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
+
+ set(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH} a)
+ run_cmake_with_options(${name}-invalid-env "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
+ run_cmake_command(${name}-invalid-env-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
+
+ unset(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH})
endfunction()
function(run_ctest_recursive name)
run_ctest(${name}-default "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
run_ctest(${name}-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
run_ctest(${name}-invalid-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a)
+
+ set(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH} 10)
+ run_ctest(${name}-env "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
+
+ set(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH} a)
+ run_ctest(${name}-invalid-env "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
+
+ unset(ENV{CMAKE_MAXIMUM_RECURSION_DEPTH})
endfunction()
run_cmake_recursive(function)
@@ -32,12 +48,8 @@ run_cmake_recursive(variable_watch)
# We run these tests separately and only with a small limit because they are
# taxing and slow. The "implicit" and "invalid" cases are already thoroughly
# covered by the other tests above.
-set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=add_subdirectory -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
-run_cmake(add_subdirectory-var)
-unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=try_compile -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
-run_cmake(try_compile-var)
-unset(RunCMake_TEST_OPTIONS)
+run_cmake_with_options(add_subdirectory-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=add_subdirectory -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
+run_cmake_with_options(try_compile-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=try_compile -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
run_ctest_recursive(ctest_read_custom_files)
diff --git a/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-stderr.txt
new file mode 100644
index 0000000..b664fa0
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env-stderr.txt
@@ -0,0 +1,34 @@
+^2
+3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:1 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
+ .*/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-env/test\.cmake:10 \(ctest_read_custom_files\)
+
+
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
+Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake$
diff --git a/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-stderr.txt
new file mode 100644
index 0000000..7dbbb3e
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-invalid-env-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:1 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-default-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-default-script-stderr.txt
index b8557ab..4e965e8 100644
--- a/Tests/RunCMake/MaxRecursionDepth/find_package-default-script-stderr.txt
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-default-script-stderr.txt
@@ -1,5 +1,7 @@
[0-9]+
-CMake Error at .*/FindRecursivePackage\.cmake:1 \(message\):
- Maximum recursion depth of [0-9]+ exceeded
+CMake Error at [^
+]*/Tests/RunCMake/MaxRecursionDepth/FindRecursivePackage.cmake:[0-9]+ \(find_package\):
+ find_package maximum nesting depth of [0-9]+ exceeded.
Call Stack \(most recent call first\):
- .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ [^
+]*/Tests/RunCMake/MaxRecursionDepth/FindRecursivePackage.cmake:[0-9]+ \(find_package\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-default-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-default-stderr.txt
index 5d31e29..0119953 100644
--- a/Tests/RunCMake/MaxRecursionDepth/find_package-default-stderr.txt
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-default-stderr.txt
@@ -1,5 +1,5 @@
[0-9]+
-CMake Error at FindRecursivePackage\.cmake:1 \(message\):
- Maximum recursion depth of [0-9]+ exceeded
+CMake Error at FindRecursivePackage.cmake:[0-9]+ \(find_package\):
+ find_package maximum nesting depth of [0-9]+ exceeded.
Call Stack \(most recent call first\):
- FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage.cmake:[0-9]+ \(find_package\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-env-script-stderr.txt
new file mode 100644
index 0000000..5314551
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-env-script-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at .*/FindRecursivePackage\.cmake:1 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ .*/find_package\.cmake:2 \(find_package\)
+ .*/CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-env-stderr.txt
new file mode 100644
index 0000000..b47a13a
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-env-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at FindRecursivePackage\.cmake:1 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage\.cmake:3 \(find_package\)
+ find_package\.cmake:2 \(find_package\)
+ CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-stderr.txt
new file mode 100644
index 0000000..4e965e8
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-script-stderr.txt
@@ -0,0 +1,7 @@
+[0-9]+
+CMake Error at [^
+]*/Tests/RunCMake/MaxRecursionDepth/FindRecursivePackage.cmake:[0-9]+ \(find_package\):
+ find_package maximum nesting depth of [0-9]+ exceeded.
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/MaxRecursionDepth/FindRecursivePackage.cmake:[0-9]+ \(find_package\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-stderr.txt
new file mode 100644
index 0000000..0119953
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-env-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at FindRecursivePackage.cmake:[0-9]+ \(find_package\):
+ find_package maximum nesting depth of [0-9]+ exceeded.
+Call Stack \(most recent call first\):
+ FindRecursivePackage.cmake:[0-9]+ \(find_package\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-script-stderr.txt
index b8557ab..4e965e8 100644
--- a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-script-stderr.txt
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-script-stderr.txt
@@ -1,5 +1,7 @@
[0-9]+
-CMake Error at .*/FindRecursivePackage\.cmake:1 \(message\):
- Maximum recursion depth of [0-9]+ exceeded
+CMake Error at [^
+]*/Tests/RunCMake/MaxRecursionDepth/FindRecursivePackage.cmake:[0-9]+ \(find_package\):
+ find_package maximum nesting depth of [0-9]+ exceeded.
Call Stack \(most recent call first\):
- .*/FindRecursivePackage\.cmake:3 \(find_package\)
+ [^
+]*/Tests/RunCMake/MaxRecursionDepth/FindRecursivePackage.cmake:[0-9]+ \(find_package\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-stderr.txt
index 5d31e29..0119953 100644
--- a/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-stderr.txt
+++ b/Tests/RunCMake/MaxRecursionDepth/find_package-invalid-var-stderr.txt
@@ -1,5 +1,5 @@
[0-9]+
-CMake Error at FindRecursivePackage\.cmake:1 \(message\):
- Maximum recursion depth of [0-9]+ exceeded
+CMake Error at FindRecursivePackage.cmake:[0-9]+ \(find_package\):
+ find_package maximum nesting depth of [0-9]+ exceeded.
Call Stack \(most recent call first\):
- FindRecursivePackage\.cmake:3 \(find_package\)
+ FindRecursivePackage.cmake:[0-9]+ \(find_package\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/function-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/function-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/function-env-script-stderr.txt
new file mode 100644
index 0000000..61304b1
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-env-script-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at .*/function\.cmake:2 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:4 \(recursive\)
+ .*/function\.cmake:7 \(recursive\)
+ .*/CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/function-env-stderr.txt
new file mode 100644
index 0000000..54e72af
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-env-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at function\.cmake:2 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:4 \(recursive\)
+ function\.cmake:7 \(recursive\)
+ CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-stderr.txt
new file mode 100644
index 0000000..92de1fb
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-script-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at .*/function\.cmake:2 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ .*/function\.cmake:4 \(recursive\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-stderr.txt
new file mode 100644
index 0000000..5c25c4b
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/function-invalid-env-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at function\.cmake:2 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ function\.cmake:4 \(recursive\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/include-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/include-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/include-env-script-stderr.txt
new file mode 100644
index 0000000..f55f505
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-env-script-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at .*/include_recursive\.cmake:1 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include_recursive\.cmake:3 \(include\)
+ .*/include\.cmake:2 \(include\)
+ .*/CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/include-env-stderr.txt
new file mode 100644
index 0000000..ff33985
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-env-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at include_recursive\.cmake:1 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include_recursive\.cmake:3 \(include\)
+ include\.cmake:2 \(include\)
+ CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-stderr.txt
new file mode 100644
index 0000000..0510e7c
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-script-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at .*/include_recursive\.cmake:1 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ .*/include_recursive\.cmake:3 \(include\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-stderr.txt
new file mode 100644
index 0000000..b1494a8
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/include-invalid-env-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at include_recursive\.cmake:1 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ include_recursive\.cmake:3 \(include\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/macro-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/macro-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/macro-env-script-stderr.txt
new file mode 100644
index 0000000..142e068
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-env-script-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at .*/macro\.cmake:2 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:4 \(recursive\)
+ .*/macro\.cmake:7 \(recursive\)
+ .*/CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/macro-env-stderr.txt
new file mode 100644
index 0000000..71de553
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-env-stderr.txt
@@ -0,0 +1,21 @@
+^3
+4
+5
+6
+7
+8
+9
+10
+CMake Error at macro\.cmake:2 \(message\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:4 \(recursive\)
+ macro\.cmake:7 \(recursive\)
+ CMakeLists\.txt:5 \(include\)$
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-stderr.txt
new file mode 100644
index 0000000..c67be57
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-script-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at .*/macro\.cmake:2 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ .*/macro\.cmake:4 \(recursive\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-stderr.txt
new file mode 100644
index 0000000..0b27162
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/macro-invalid-env-stderr.txt
@@ -0,0 +1,5 @@
+[0-9]+
+CMake Error at macro\.cmake:2 \(message\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ macro\.cmake:4 \(recursive\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-stderr.txt
new file mode 100644
index 0000000..52fedd3
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-script-stderr.txt
@@ -0,0 +1,22 @@
+^4
+6
+8
+10
+CMake Error at .*/variable_watch\.cmake:[0-9]+ \(update_x\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ .*/variable_watch\.cmake:5 \(set\)
+ .*/variable_watch\.cmake:[0-9]+ \(update_x\)
+ .*/variable_watch\.cmake:5 \(set\)
+ .*/variable_watch\.cmake:[0-9]+ \(update_x\)
+ .*/variable_watch\.cmake:5 \(set\)
+ .*/variable_watch\.cmake:[0-9]+ \(update_x\)
+ .*/variable_watch\.cmake:5 \(set\)
+ .*/variable_watch\.cmake:[0-9]+ \(update_x\)
+ .*/variable_watch\.cmake:9 \(set\)
+ .*/CMakeLists\.txt:5 \(include\)
+
+
+CMake Error: Error in cmake code at
+Unknown:0:
+A command failed during the invocation of callback "update_x"\.$
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-stderr.txt
new file mode 100644
index 0000000..1427f1d
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-env-stderr.txt
@@ -0,0 +1,22 @@
+^4
+6
+8
+10
+CMake Error at variable_watch\.cmake:[0-9]+ \(update_x\):
+ Maximum recursion depth of 10 exceeded
+Call Stack \(most recent call first\):
+ variable_watch\.cmake:5 \(set\)
+ variable_watch\.cmake:[0-9]+ \(update_x\)
+ variable_watch\.cmake:5 \(set\)
+ variable_watch\.cmake:[0-9]+ \(update_x\)
+ variable_watch\.cmake:5 \(set\)
+ variable_watch\.cmake:[0-9]+ \(update_x\)
+ variable_watch\.cmake:5 \(set\)
+ variable_watch\.cmake:[0-9]+ \(update_x\)
+ variable_watch\.cmake:9 \(set\)
+ CMakeLists\.txt:5 \(include\)
+
+
+CMake Error: Error in cmake code at
+Unknown:0:
+A command failed during the invocation of callback "update_x"\.$
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-result.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-result.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-stderr.txt
new file mode 100644
index 0000000..07deee2
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-script-stderr.txt
@@ -0,0 +1,6 @@
+[0-9]+
+CMake Error at .*/variable_watch\.cmake:[0-9]+ \(update_x\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ .*/variable_watch\.cmake:5 \(set\)
+ .*/variable_watch\.cmake:[0-9]+ \(update_x\)
diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-stderr.txt
new file mode 100644
index 0000000..b2395b3
--- /dev/null
+++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-env-stderr.txt
@@ -0,0 +1,6 @@
+[0-9]+
+CMake Error at variable_watch\.cmake:[0-9]+ \(update_x\):
+ Maximum recursion depth of [0-9]+ exceeded
+Call Stack \(most recent call first\):
+ variable_watch\.cmake:5 \(set\)
+ variable_watch\.cmake:[0-9]+ \(update_x\)
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index a07b6e9..2ccaf9a 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -1,113 +1,123 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+# BEGIN imports
+
import os
import re
from dataclasses import dataclass
-from typing import Any, cast
+from typing import Any, List, Tuple, Type, cast
+
+import sphinx
+
+from docutils.utils.code_analyzer import Lexer, LexerError
+from docutils.parsers.rst import Directive, directives
+from docutils.transforms import Transform
+from docutils.nodes import Element, Node, TextElement, system_message
+from docutils import io, nodes
+
+from sphinx.directives import ObjectDescription, nl_escape_re
+from sphinx.domains import Domain, ObjType
+from sphinx.roles import XRefRole
+from sphinx.util.docutils import ReferenceRole
+from sphinx.util.nodes import make_refnode
+from sphinx.util import logging, ws_re
+from sphinx import addnodes
+
+# END imports
+
+# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+# BEGIN pygments tweaks
# Override much of pygments' CMakeLexer.
# We need to parse CMake syntax definitions, not CMake code.
# For hard test cases that use much of the syntax below, see
-# - module/FindPkgConfig.html (with "glib-2.0>=2.10 gtk+-2.0" and similar)
-# - module/ExternalProject.html (with http:// https:// git@; also has command options -E --build)
-# - manual/cmake-buildsystem.7.html (with nested $<..>; relative and absolute paths, "::")
+# - module/FindPkgConfig.html
+# (with "glib-2.0>=2.10 gtk+-2.0" and similar)
+# - module/ExternalProject.html
+# (with http:// https:// git@; also has command options -E --build)
+# - manual/cmake-buildsystem.7.html
+# (with nested $<..>; relative and absolute paths, "::")
from pygments.lexers import CMakeLexer
-from pygments.token import Name, Operator, Punctuation, String, Text, Comment, Generic, Whitespace, Number
+from pygments.token import (Comment, Name, Number, Operator, Punctuation,
+ String, Text, Whitespace)
from pygments.lexer import bygroups
-# RE to split multiple command signatures
-sig_end_re = re.compile(r'(?<=[)])\n')
-
# Notes on regular expressions below:
# - [\.\+-] are needed for string constants like gtk+-2.0
-# - Unix paths are recognized by '/'; support for Windows paths may be added if needed
+# - Unix paths are recognized by '/'; support for Windows paths may be added
+# if needed
# - (\\.) allows for \-escapes (used in manual/cmake-language.7)
# - $<..$<..$>..> nested occurrence in cmake-buildsystem
-# - Nested variable evaluations are only supported in a limited capacity. Only
-# one level of nesting is supported and at most one nested variable can be present.
+# - Nested variable evaluations are only supported in a limited capacity.
+# Only one level of nesting is supported and at most one nested variable can
+# be present.
CMakeLexer.tokens["root"] = [
- (r'\b(\w+)([ \t]*)(\()', bygroups(Name.Function, Text, Name.Function), '#push'), # fctn(
+ # fctn(
+ (r'\b(\w+)([ \t]*)(\()',
+ bygroups(Name.Function, Text, Name.Function), '#push'),
(r'\(', Name.Function, '#push'),
(r'\)', Name.Function, '#pop'),
(r'\[', Punctuation, '#push'),
(r'\]', Punctuation, '#pop'),
(r'[|;,.=*\-]', Punctuation),
- (r'\\\\', Punctuation), # used in commands/source_group
+ # used in commands/source_group
+ (r'\\\\', Punctuation),
(r'[:]', Operator),
- (r'[<>]=', Punctuation), # used in FindPkgConfig.cmake
- (r'\$<', Operator, '#push'), # $<...>
- (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable), # <expr>
- (r'(\$\w*\{)([^\}\$]*)?(?:(\$\w*\{)([^\}]+?)(\}))?([^\}]*?)(\})', # ${..} $ENV{..}, possibly nested
- bygroups(Operator, Name.Tag, Operator, Name.Tag, Operator, Name.Tag, Operator)),
- (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)), # DATA{ ...}
- (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute), # URL, git@, ...
- (r'/\w[\w\.\+-/\\]*', Name.Attribute), # absolute path
+ # used in FindPkgConfig.cmake
+ (r'[<>]=', Punctuation),
+ # $<...>
+ (r'\$<', Operator, '#push'),
+ # <expr>
+ (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable),
+ # ${..} $ENV{..}, possibly nested
+ (r'(\$\w*\{)([^\}\$]*)?(?:(\$\w*\{)([^\}]+?)(\}))?([^\}]*?)(\})',
+ bygroups(Operator, Name.Tag, Operator, Name.Tag, Operator, Name.Tag,
+ Operator)),
+ # DATA{ ...}
+ (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)),
+ # URL, git@, ...
+ (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute),
+ # absolute path
+ (r'/\w[\w\.\+-/\\]*', Name.Attribute),
(r'/', Name.Attribute),
- (r'\w[\w\.\+-]*/[\w.+-/\\]*', Name.Attribute), # relative path
- (r'[A-Z]((\\.)|[\w.+-])*[a-z]((\\.)|[\w.+-])*', Name.Builtin), # initial A-Z, contains a-z
+ # relative path
+ (r'\w[\w\.\+-]*/[\w.+-/\\]*', Name.Attribute),
+ # initial A-Z, contains a-z
+ (r'[A-Z]((\\.)|[\w.+-])*[a-z]((\\.)|[\w.+-])*', Name.Builtin),
(r'@?[A-Z][A-Z0-9_]*', Name.Constant),
(r'[a-z_]((\\;)|(\\ )|[\w.+-])*', Name.Builtin),
(r'[0-9][0-9\.]*', Number),
- (r'(?s)"(\\"|[^"])*"', String), # "string"
+ # "string"
+ (r'(?s)"(\\"|[^"])*"', String),
(r'\.\.\.', Name.Variable),
- (r'<', Operator, '#push'), # <..|..> is different from <expr>
+ # <..|..> is different from <expr>
+ (r'<', Operator, '#push'),
(r'>', Operator, '#pop'),
(r'\n', Whitespace),
(r'[ \t]+', Whitespace),
(r'#.*\n', Comment),
- # (r'[^<>\])\}\|$"# \t\n]+', Name.Exception), # fallback, for debugging only
+ # fallback, for debugging only
+ # (r'[^<>\])\}\|$"# \t\n]+', Name.Exception),
]
-from docutils.utils.code_analyzer import Lexer, LexerError
-from docutils.parsers.rst import Directive, directives
-from docutils.transforms import Transform
-from docutils import io, nodes
+# END pygments tweaks
-from sphinx.directives import ObjectDescription, nl_escape_re
-from sphinx.domains import Domain, ObjType
-from sphinx.roles import XRefRole
-from sphinx.util.nodes import make_refnode
-from sphinx.util import logging, ws_re
-from sphinx import addnodes
+# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+# Require at least Sphinx 2.x.
+assert sphinx.version_info >= (2,)
logger = logging.getLogger(__name__)
-sphinx_before_1_4 = False
-sphinx_before_1_7_2 = False
-try:
- from sphinx import version_info
- if version_info < (1, 4):
- sphinx_before_1_4 = True
- if version_info < (1, 7, 2):
- sphinx_before_1_7_2 = True
-except ImportError:
- # The `sphinx.version_info` tuple was added in Sphinx v1.2:
- sphinx_before_1_4 = True
- sphinx_before_1_7_2 = True
-
-if sphinx_before_1_7_2:
- # Monkey patch for sphinx generating invalid content for qcollectiongenerator
- # https://github.com/sphinx-doc/sphinx/issues/1435
- from sphinx.util.pycompat import htmlescape
- from sphinx.builders.qthelp import QtHelpBuilder
- old_build_keywords = QtHelpBuilder.build_keywords
- def new_build_keywords(self, title, refs, subitems):
- old_items = old_build_keywords(self, title, refs, subitems)
- new_items = []
- for item in old_items:
- before, rest = item.split("ref=\"", 1)
- ref, after = rest.split("\"")
- if ("<" in ref and ">" in ref):
- new_items.append(before + "ref=\"" + htmlescape(ref) + "\"" + after)
- else:
- new_items.append(item)
- return new_items
- QtHelpBuilder.build_keywords = new_build_keywords
+# RE to split multiple command signatures.
+sig_end_re = re.compile(r'(?<=[)])\n')
+
@dataclass
class ObjectEntry:
@@ -130,7 +140,7 @@ class CMakeModule(Directive):
def run(self):
settings = self.state.document.settings
if not settings.file_insertion_enabled:
- raise self.warning('"%s" directive disabled.' % self.name)
+ raise self.warning(f'{self.name!r} directive disabled.')
env = self.state.document.settings.env
rel_path, path = env.relfn2path(self.arguments[0])
@@ -141,13 +151,12 @@ class CMakeModule(Directive):
settings.record_dependencies.add(path)
f = io.FileInput(source_path=path, encoding=encoding,
error_handler=e_handler)
- except UnicodeEncodeError as error:
- msg = ('Problems with "%s" directive path:\n'
- 'Cannot encode input file path "%s" '
- '(wrong locale?).' % (self.name, path))
+ except UnicodeEncodeError:
+ msg = (f'Problems with {self.name!r} directive path:\n'
+ f'Cannot encode input file path {path!r} (wrong locale?).')
raise self.severe(msg)
except IOError as error:
- msg = 'Problems with "%s" directive path:\n%s.' % (self.name, error)
+ msg = f'Problems with {self.name!r} directive path:\n{error}.'
raise self.severe(msg)
raw_lines = f.read().splitlines()
f.close()
@@ -167,7 +176,7 @@ class CMakeModule(Directive):
# Line mode: check for .rst start (bracket or line)
m = self.re_start.match(line)
if m:
- rst = ']%s]' % m.group('eq')
+ rst = f']{m.group("eq")}]'
line = ''
elif line == '#.rst:':
rst = '#'
@@ -182,21 +191,19 @@ class CMakeModule(Directive):
line = ''
lines.append(line)
if rst is not None and rst != '#':
- raise self.warning('"%s" found unclosed bracket "#[%s[.rst:" in %s' %
- (self.name, rst[1:-1], path))
+ raise self.warning(f'{self.name!r} found unclosed bracket '
+ f'"#[{rst[1:-1]}[.rst:" in {path!r}')
self.state_machine.insert_input(lines, path)
return []
+
class _cmake_index_entry:
def __init__(self, desc):
self.desc = desc
- def __call__(self, title, targetid, main = 'main'):
- # See https://github.com/sphinx-doc/sphinx/issues/2673
- if sphinx_before_1_4:
- return ('pair', u'%s ; %s' % (self.desc, title), targetid, main)
- else:
- return ('pair', u'%s ; %s' % (self.desc, title), targetid, main, None)
+ def __call__(self, title, targetid, main='main'):
+ return ('pair', f'{self.desc} ; {title}', targetid, main, None)
+
_cmake_index_objs = {
'command': _cmake_index_entry('command'),
@@ -218,6 +225,7 @@ _cmake_index_objs = {
'variable': _cmake_index_entry('variable'),
}
+
class CMakeTransform(Transform):
# Run this transform early since we insert nodes we want
@@ -244,7 +252,8 @@ class CMakeTransform(Transform):
title = False
else:
for line in f:
- if len(line) > 0 and (line[0].isalnum() or line[0] == '<' or line[0] == '$'):
+ if len(line) > 0 and (line[0].isalnum() or
+ line[0] == '<' or line[0] == '$'):
title = line.rstrip()
break
f.close()
@@ -272,7 +281,7 @@ class CMakeTransform(Transform):
if m:
title = m.group(1)
targetname = title
- targetid = '%s:%s' % (objtype, targetname)
+ targetid = f'{objtype}:{targetname}'
targetnode = nodes.target('', '', ids=[targetid])
self.document.note_explicit_target(targetnode)
self.document.insert(0, targetnode)
@@ -285,23 +294,25 @@ class CMakeTransform(Transform):
domain = cast(CMakeDomain, env.get_domain('cmake'))
domain.note_object(objtype, targetname, targetid, targetid)
+
class CMakeObject(ObjectDescription):
+ def __init__(self, *args, **kwargs):
+ self.targetname = None
+ super().__init__(*args, **kwargs)
def handle_signature(self, sig, signode):
# called from sphinx.directives.ObjectDescription.run()
signode += addnodes.desc_name(sig, sig)
- if self.objtype == 'genex':
- m = CMakeXRefRole._re_genex.match(sig)
- if m:
- sig = m.group(1)
return sig
def add_target_and_index(self, name, sig, signode):
if self.objtype == 'command':
targetname = name.lower()
+ elif self.targetname:
+ targetname = self.targetname
else:
targetname = name
- targetid = '%s:%s' % (self.objtype, targetname)
+ targetid = f'{self.objtype}:{targetname}'
if targetid not in self.state.document.ids:
signode['names'].append(targetid)
signode['ids'].append(targetid)
@@ -316,17 +327,95 @@ class CMakeObject(ObjectDescription):
if make_index_entry:
self.indexnode['entries'].append(make_index_entry(name, targetid))
+
+class CMakeGenexObject(CMakeObject):
+ option_spec = {
+ 'target': directives.unchanged,
+ }
+
+ def handle_signature(self, sig, signode):
+ name = super().handle_signature(sig, signode)
+
+ m = CMakeXRefRole._re_genex.match(sig)
+ if m:
+ name = m.group(1)
+
+ return name
+
+ def run(self):
+ target = self.options.get('target')
+ if target is not None:
+ self.targetname = target
+
+ return super().run()
+
+
class CMakeSignatureObject(CMakeObject):
object_type = 'signature'
+ BREAK_ALL = 'all'
+ BREAK_SMART = 'smart'
+ BREAK_VERBATIM = 'verbatim'
+
+ BREAK_CHOICES = {BREAK_ALL, BREAK_SMART, BREAK_VERBATIM}
+
+ def break_option(argument):
+ return directives.choice(argument, CMakeSignatureObject.BREAK_CHOICES)
+
option_spec = {
'target': directives.unchanged,
+ 'break': break_option,
}
- def get_signatures(self):
+ def _break_signature_all(sig: str) -> str:
+ return ws_re.sub(' ', sig)
+
+ def _break_signature_verbatim(sig: str) -> str:
+ lines = [ws_re.sub('\xa0', line.strip()) for line in sig.split('\n')]
+ return ' '.join(lines)
+
+ def _break_signature_smart(sig: str) -> str:
+ tokens = []
+ for line in sig.split('\n'):
+ token = ''
+ delim = ''
+
+ for c in line.strip():
+ if len(delim) == 0 and ws_re.match(c):
+ if len(token):
+ tokens.append(ws_re.sub('\xa0', token))
+ token = ''
+ else:
+ if c == '[':
+ delim += ']'
+ elif c == '<':
+ delim += '>'
+ elif len(delim) and c == delim[-1]:
+ delim = delim[:-1]
+ token += c
+
+ if len(token):
+ tokens.append(ws_re.sub('\xa0', token))
+
+ return ' '.join(tokens)
+
+ def __init__(self, *args, **kwargs):
+ self.targetnames = {}
+ self.break_style = CMakeSignatureObject.BREAK_SMART
+ super().__init__(*args, **kwargs)
+
+ def get_signatures(self) -> List[str]:
content = nl_escape_re.sub('', self.arguments[0])
lines = sig_end_re.split(content)
- return [ws_re.sub(' ', line.strip()) for line in lines]
+
+ if self.break_style == CMakeSignatureObject.BREAK_VERBATIM:
+ fixup = CMakeSignatureObject._break_signature_verbatim
+ elif self.break_style == CMakeSignatureObject.BREAK_SMART:
+ fixup = CMakeSignatureObject._break_signature_smart
+ else:
+ fixup = CMakeSignatureObject._break_signature_all
+
+ return [fixup(line.strip()) for line in lines]
def handle_signature(self, sig, signode):
language = 'cmake'
@@ -344,7 +433,9 @@ class CMakeSignatureObject(CMakeObject):
raise self.warning(error)
for classes, value in tokens:
- if classes:
+ if value == '\xa0':
+ node += nodes.inline(value, value, classes=['nbsp'])
+ elif classes:
node += nodes.inline(value, value, classes=classes)
else:
node += nodes.Text(value)
@@ -354,13 +445,10 @@ class CMakeSignatureObject(CMakeObject):
return sig
- def __init__(self, *args, **kwargs):
- self.targetnames = {}
- super().__init__(*args, **kwargs)
-
def add_target_and_index(self, name, sig, signode):
- if name in self.targetnames:
- sigargs = self.targetnames[name]
+ sig = sig.replace('\xa0', ' ')
+ if sig in self.targetnames:
+ sigargs = self.targetnames[sig]
else:
def extract_keywords(params):
for p in params:
@@ -369,7 +457,7 @@ class CMakeSignatureObject(CMakeObject):
else:
return
- keywords = extract_keywords(name.split('(')[1].split())
+ keywords = extract_keywords(sig.split('(')[1].split())
sigargs = ' '.join(keywords)
targetname = sigargs.lower()
targetid = nodes.make_id(targetname)
@@ -381,7 +469,7 @@ class CMakeSignatureObject(CMakeObject):
self.state.document.note_explicit_target(signode)
# Register the signature as a command object.
- command = name.split('(')[0].lower()
+ command = sig.split('(')[0].lower()
refname = f'{command}({sigargs})'
refid = f'command:{command}({targetname})'
@@ -390,6 +478,8 @@ class CMakeSignatureObject(CMakeObject):
node_id=targetid, location=signode)
def run(self):
+ self.break_style = CMakeSignatureObject.BREAK_ALL
+
targets = self.options.get('target')
if targets is not None:
signatures = self.get_signatures()
@@ -397,38 +487,79 @@ class CMakeSignatureObject(CMakeObject):
for signature, target in zip(signatures, targets):
self.targetnames[signature] = target
+ self.break_style = (
+ self.options.get('break', CMakeSignatureObject.BREAK_SMART))
+
return super().run()
-class CMakeXRefRole(XRefRole):
+class CMakeReferenceRole:
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
- _re_ref = re.compile(r'^.*\s<\w+([(][\w\s]+[)])?>$', re.DOTALL)
+
+ @staticmethod
+ def _escape_angle_brackets(text: str) -> str:
+ # CMake cross-reference targets frequently contain '<' so escape
+ # any explicit `<target>` with '<' not preceded by whitespace.
+ while True:
+ m = CMakeReferenceRole._re.match(text)
+ if m and len(m.group(2)) == 0:
+ text = f'{m.group(1)}\x00<{m.group(3)}>'
+ else:
+ break
+ return text
+
+ def __class_getitem__(cls, parent: Any):
+ class Class(parent):
+ def __call__(self, name: str, rawtext: str, text: str,
+ *args, **kwargs
+ ) -> Tuple[List[Node], List[system_message]]:
+ text = CMakeReferenceRole._escape_angle_brackets(text)
+ return super().__call__(name, rawtext, text, *args, **kwargs)
+ return Class
+
+
+class CMakeCRefRole(CMakeReferenceRole[ReferenceRole]):
+ nodeclass: Type[Element] = nodes.reference
+ innernodeclass: Type[TextElement] = nodes.literal
+ classes: List[str] = ['cmake', 'literal']
+
+ def run(self) -> Tuple[List[Node], List[system_message]]:
+ refnode = self.nodeclass(self.rawtext)
+ self.set_source_info(refnode)
+
+ refnode['refid'] = nodes.make_id(self.target)
+ refnode += self.innernodeclass(self.rawtext, self.title,
+ classes=self.classes)
+
+ return [refnode], []
+
+
+class CMakeXRefRole(CMakeReferenceRole[XRefRole]):
+
+ _re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
_re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL)
_re_guide = re.compile(r'^([^<>/]+)/([^<>]*)$', re.DOTALL)
- def __call__(self, typ, rawtext, text, *args, **keys):
+ def __call__(self, typ, rawtext, text, *args, **kwargs):
if typ == 'cmake:command':
- m = CMakeXRefRole._re_ref.match(text)
- if m is None:
+ # Translate a CMake command cross-reference of the form:
+ # `command_name(SUB_COMMAND)`
+ # to be its own explicit target:
+ # `command_name(SUB_COMMAND) <command_name(SUB_COMMAND)>`
+ # so the XRefRole `fix_parens` option does not add more `()`.
+ m = CMakeXRefRole._re_sub.match(text)
+ if m:
text = f'{text} <{text}>'
elif typ == 'cmake:genex':
m = CMakeXRefRole._re_genex.match(text)
if m:
- text = '%s <%s>' % (text, m.group(1))
+ text = f'{text} <{m.group(1)}>'
elif typ == 'cmake:guide':
m = CMakeXRefRole._re_guide.match(text)
if m:
- text = '%s <%s>' % (m.group(2), text)
- # CMake cross-reference targets frequently contain '<' so escape
- # any explicit `<target>` with '<' not preceded by whitespace.
- while True:
- m = CMakeXRefRole._re.match(text)
- if m and len(m.group(2)) == 0:
- text = '%s\x00<%s>' % (m.group(1), m.group(3))
- else:
- break
- return XRefRole.__call__(self, typ, rawtext, text, *args, **keys)
+ text = f'{m.group(2)} <{text}>'
+ return super().__call__(typ, rawtext, text, *args, **kwargs)
# We cannot insert index nodes using the result_nodes method
# because CMakeXRefRole is processed before substitution_reference
@@ -441,6 +572,7 @@ class CMakeXRefRole(XRefRole):
# def result_nodes(self, document, env, node, is_ref):
# pass
+
class CMakeXRefTransform(Transform):
# Run this transform early since we insert nodes we want
@@ -471,9 +603,9 @@ class CMakeXRefTransform(Transform):
# Index signature references to their parent command.
objname = objname.split('(')[0].lower()
- targetnum = env.new_serialno('index-%s:%s' % (objtype, objname))
+ targetnum = env.new_serialno(f'index-{objtype}:{objname}')
- targetid = 'index-%s-%s:%s' % (targetnum, objtype, objname)
+ targetid = f'index-{targetnum}-{objtype}:{objname}'
targetnode = nodes.target('', '', ids=[targetid])
self.document.note_explicit_target(targetnode)
@@ -481,6 +613,7 @@ class CMakeXRefTransform(Transform):
indexnode['entries'] = [make_index_entry(objname, targetid, '')]
ref.replace_self([indexnode, targetnode, ref])
+
class CMakeDomain(Domain):
"""CMake domain."""
name = 'cmake'
@@ -507,13 +640,14 @@ class CMakeDomain(Domain):
directives = {
'command': CMakeObject,
'envvar': CMakeObject,
- 'genex': CMakeObject,
+ 'genex': CMakeGenexObject,
'signature': CMakeSignatureObject,
'variable': CMakeObject,
# Other `object_types` cannot be created except by the `CMakeTransform`
}
roles = {
- 'command': CMakeXRefRole(fix_parens = True, lowercase = True),
+ 'cref': CMakeCRefRole(),
+ 'command': CMakeXRefRole(fix_parens=True, lowercase=True),
'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
@@ -578,6 +712,7 @@ class CMakeDomain(Domain):
for refname, obj in self.data['objects'].items():
yield (refname, obj.name, obj.objtype, obj.docname, obj.node_id, 1)
+
def setup(app):
app.add_directive('cmake-module', CMakeModule)
app.add_transform(CMakeTransform)
diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css
index dd0dd02..6303cb1 100644
--- a/Utilities/Sphinx/static/cmake.css
+++ b/Utilities/Sphinx/static/cmake.css
@@ -40,6 +40,22 @@ div.sphinxsidebarwrapper {
font-weight: normal;
}
+/* Implement non-breaking spaces in signatures. */
+.nbsp {
+ white-space: nowrap;
+}
+
+/* Add hanging indent to version-{added,changed} content. */
+div .versionadded > *,
+div .versionchanged > * {
+ padding-left: 2em;
+}
+
+div.versionadded > :first-child,
+div.versionchanged > :first-child {
+ text-indent: -2em;
+}
+
/* Remove unwanted margin in case list item contains a div-wrapping
directive like `.. versionadded` or `.. deprecated`. */
dd > :first-child > p {