diff options
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 { |