diff options
499 files changed, 9578 insertions, 1838 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b26172d360..6a4140661b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -664,6 +664,13 @@ t:intel2021.8.0-makefiles: CMAKE_CI_BUILD_NAME: intel2021.8.0_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2023.0.0-el8 +t:intel2021.9.0-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2021.9.0_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2023.1.0-el8 + t:oneapi2021.1.1-makefiles: extends: - .cmake_test_linux_inteloneapi_makefiles @@ -727,6 +734,13 @@ t:oneapi2023.0.0-makefiles: CMAKE_CI_BUILD_NAME: oneapi2023.0.0_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2023.0.0-el8 +t:oneapi2023.1.0-makefiles: + extends: + - .cmake_test_linux_inteloneapi_makefiles + variables: + CMAKE_CI_BUILD_NAME: oneapi2023.1.0_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2023.1.0-el8 + b:linux-x86_64-package: extends: - .linux_package @@ -1164,6 +1178,36 @@ t:windows-clang16.0-gnu-nmake: CMAKE_CI_BUILD_NAME: windows_clang16.0_gnu_nmake CMAKE_CI_JOB_NIGHTLY: "true" +t:windows-intel2021.9.0-ninja: + extends: + - .windows_intelclassic_ninja + - .cmake_test_windows_external + - .windows_x86_64_tags_concurrent + - .cmake_junit_artifacts + - .run_dependent + dependencies: + - t:windows-vs2022-x64-ninja + needs: + - t:windows-vs2022-x64-ninja + variables: + CMAKE_CI_BUILD_NAME: windows_intel2021.9.0_ninja + CMAKE_CI_JOB_NIGHTLY: "true" + +t:windows-oneapi2023.1.0-ninja: + extends: + - .windows_inteloneapi_ninja + - .cmake_test_windows_external + - .windows_x86_64_tags_concurrent + - .cmake_junit_artifacts + - .run_dependent + dependencies: + - t:windows-vs2022-x64-ninja + needs: + - t:windows-vs2022-x64-ninja + variables: + CMAKE_CI_BUILD_NAME: windows_oneapi2023.1.0_ninja + CMAKE_CI_JOB_NIGHTLY: "true" + t:mingw_osdn_io-mingw_makefiles: extends: - .mingw_osdn_io_mingw_makefiles diff --git a/.gitlab/.gitignore b/.gitlab/.gitignore index 10d03cacd4..852dfa64d8 100644 --- a/.gitlab/.gitignore +++ b/.gitlab/.gitignore @@ -2,7 +2,9 @@ /5.15.1-0-202009071110* /bcc* /cmake* +/intel /ispc* +/innosetup /jom /llvm* /mingw diff --git a/.gitlab/ci/configure_windows_intelclassic_ninja.cmake b/.gitlab/ci/configure_windows_intelclassic_ninja.cmake new file mode 100644 index 0000000000..c2d708baf3 --- /dev/null +++ b/.gitlab/ci/configure_windows_intelclassic_ninja.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_intelcompiler_common.cmake") diff --git a/.gitlab/ci/configure_windows_intelcompiler_common.cmake b/.gitlab/ci/configure_windows_intelcompiler_common.cmake new file mode 100644 index 0000000000..55dce1d3ed --- /dev/null +++ b/.gitlab/ci/configure_windows_intelcompiler_common.cmake @@ -0,0 +1,5 @@ +set(CMake_TEST_Java OFF CACHE BOOL "") + +set(configure_no_sccache 1) + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/configure_windows_inteloneapi_ninja.cmake b/.gitlab/ci/configure_windows_inteloneapi_ninja.cmake new file mode 100644 index 0000000000..c2d708baf3 --- /dev/null +++ b/.gitlab/ci/configure_windows_inteloneapi_ninja.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_intelcompiler_common.cmake") diff --git a/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake b/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake index 5bf0be89e2..54abf722a4 100644 --- a/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake +++ b/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake @@ -1,4 +1,5 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "") + set(CMake_TEST_CPACK_INNOSETUP "ON" CACHE STRING "") set(CMake_TEST_ISPC "ON" CACHE STRING "") endif() set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "") diff --git a/.gitlab/ci/env_windows_intelclassic_ninja.ps1 b/.gitlab/ci/env_windows_intelclassic_ninja.ps1 new file mode 100755 index 0000000000..99f83b9cf1 --- /dev/null +++ b/.gitlab/ci/env_windows_intelclassic_ninja.ps1 @@ -0,0 +1,9 @@ +. .gitlab/ci/ninja-env.ps1 +. .gitlab/ci/intel-env.ps1 + +$env:CC = "icl" +$env:CXX = "icl" +$env:FC = "ifort" + +cmd /c "icl 2>&1" | Select -First 1 +cmd /c "ifort 2>&1" | Select -First 1 diff --git a/.gitlab/ci/env_windows_inteloneapi_ninja.ps1 b/.gitlab/ci/env_windows_inteloneapi_ninja.ps1 new file mode 100755 index 0000000000..3bd1d46b48 --- /dev/null +++ b/.gitlab/ci/env_windows_inteloneapi_ninja.ps1 @@ -0,0 +1,9 @@ +. .gitlab/ci/ninja-env.ps1 +. .gitlab/ci/intel-env.ps1 + +$env:CC = "icx" +$env:CXX = "icx" +$env:FC = "ifx" + +cmd /c "icx 2>&1" | Select -First 1 +cmd /c "ifx 2>&1" | Select -First 1 diff --git a/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 b/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 index a96658dd0f..50a03ca828 100755 --- a/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 +++ b/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 @@ -1,3 +1,4 @@ if ("$env:CMAKE_CI_NIGHTLY" -eq "true") { + . ".gitlab/ci/innosetup-env.ps1" . ".gitlab/ci/ispc-env.ps1" } diff --git a/.gitlab/ci/innosetup-env.ps1 b/.gitlab/ci/innosetup-env.ps1 new file mode 100755 index 0000000000..96e9d8c322 --- /dev/null +++ b/.gitlab/ci/innosetup-env.ps1 @@ -0,0 +1,4 @@ +$pwdpath = $pwd.Path +& "$pwsh" -File ".gitlab/ci/innosetup.ps1" +Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\innosetup;$env:PATH" +ISCC 2>$null | Select -First 1 diff --git a/.gitlab/ci/innosetup.ps1 b/.gitlab/ci/innosetup.ps1 new file mode 100755 index 0000000000..a7f4eb31c3 --- /dev/null +++ b/.gitlab/ci/innosetup.ps1 @@ -0,0 +1,20 @@ +$erroractionpreference = "stop" + +$version = "6.2.2-1" +$sha256sum = "34D5311070678617424628A88C8A7F7BE41157B1A59112F9DFDA1D7EFD4469CC" +$filename = "innosetup-$version" +$tarball = "$filename.zip" + +$outdir = $pwd.Path +$outdir = "$outdir\.gitlab" +$ProgressPreference = 'SilentlyContinue' +Invoke-WebRequest -Uri "https://cmake.org/files/dependencies/internal/$tarball" -OutFile "$outdir\$tarball" +$hash = Get-FileHash "$outdir\$tarball" -Algorithm SHA256 +if ($hash.Hash -ne $sha256sum) { + exit 1 +} + +Add-Type -AssemblyName System.IO.Compression.FileSystem +[System.IO.Compression.ZipFile]::ExtractToDirectory("$outdir\$tarball", "$outdir") +Move-Item -Path "$outdir\$filename" -Destination "$outdir\innosetup" +Remove-Item "$outdir\$tarball" diff --git a/.gitlab/ci/intel-env.ps1 b/.gitlab/ci/intel-env.ps1 new file mode 100755 index 0000000000..75f7286381 --- /dev/null +++ b/.gitlab/ci/intel-env.ps1 @@ -0,0 +1,4 @@ +$pwdpath = $pwd.Path +& "$pwsh" -File ".gitlab/ci/intel.ps1" +Invoke-Expression -Command .gitlab/ci/vcvarsall.ps1 +Invoke-Expression -Command .gitlab/ci/intel-vars.ps1 diff --git a/.gitlab/ci/intel-vars.ps1 b/.gitlab/ci/intel-vars.ps1 new file mode 100755 index 0000000000..dde0aa26ea --- /dev/null +++ b/.gitlab/ci/intel-vars.ps1 @@ -0,0 +1,9 @@ +$erroractionpreference = "stop" + +cmd /c "`".gitlab\intel\setvars.bat`" & set" | +foreach { + if ($_ -match "=") { + $v = $_.split("=") + [Environment]::SetEnvironmentVariable($v[0], $v[1]) + } +} diff --git a/.gitlab/ci/intel.ps1 b/.gitlab/ci/intel.ps1 new file mode 100755 index 0000000000..2262669d89 --- /dev/null +++ b/.gitlab/ci/intel.ps1 @@ -0,0 +1,42 @@ +$erroractionpreference = "stop" + +if ("$env:CMAKE_CI_BUILD_NAME" -match "(^|_)(oneapi2023\.1\.0|intel2021\.9\.0)(_|$)") { + # Intel oneAPI 2023.1.0 + $version = "2023.1.0" + $filename = "intel-oneapi-$version-windows-1" + $sha256sum = "5AFCA9E0B03894565209B1295476163ABEBB1F1388E0F3EF5B4D0F9189E65BDC" +} else { + throw ('unknown CMAKE_CI_BUILD_NAME: ' + "$env:CMAKE_CI_BUILD_NAME") +} +$tarball = "$filename.zip" + +$outdir = $pwd.Path +$outdir = "$outdir\.gitlab" +$ProgressPreference = 'SilentlyContinue' +# This URL is only visible inside of Kitware's network. See above filename table. +Invoke-WebRequest -Uri "https://cmake.org/files/dependencies/internal/$tarball" -OutFile "$outdir\$tarball" +$hash = Get-FileHash "$outdir\$tarball" -Algorithm SHA256 +if ($hash.Hash -ne $sha256sum) { + exit 1 +} + +Add-Type -AssemblyName System.IO.Compression.FileSystem +[System.IO.Compression.ZipFile]::ExtractToDirectory("$outdir\$tarball", "$outdir") +Move-Item -Path "$outdir\$filename" -Destination "$outdir\intel" +Remove-Item "$outdir\$tarball" + +$compiler = "$outdir\intel\compiler" +$bin = "$compiler\$version\windows\bin" +$null = New-Item -ItemType Junction -Path "$compiler\latest" -Target "$compiler\$version" +$null = New-Item -ItemType HardLink -Path "$bin\icx-cl.exe" -Target "$bin\icx.exe" +$null = New-Item -ItemType HardLink -Path "$bin\icx-cc.exe" -Target "$bin\icx.exe" +$null = New-Item -ItemType HardLink -Path "$bin\icpx.exe" -Target "$bin\icx.exe" +$bin = "$compiler\$version\windows\bin-llvm" +$null = New-Item -ItemType HardLink -Path "$bin\clang-cl.exe" -Target "$bin\clang.exe" +$null = New-Item -ItemType HardLink -Path "$bin\clang-cpp.exe" -Target "$bin\clang.exe" +$null = New-Item -ItemType HardLink -Path "$bin\clang++.exe" -Target "$bin\clang.exe" +$null = New-Item -ItemType HardLink -Path "$bin\lld-link.exe" -Target "$bin\lld.exe" +$null = New-Item -ItemType HardLink -Path "$bin\ld.lld.exe" -Target "$bin\lld.exe" +$null = New-Item -ItemType HardLink -Path "$bin\llvm-lib.exe" -Target "$bin\llvm-ar.exe" +Clear-Variable -Name bin +Clear-Variable -Name compiler diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index f1e86ad3e5..07a479e045 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -222,6 +222,22 @@ variables: CMAKE_CONFIGURATION: windows_msvc_v71_nmake +.windows_intelclassic_ninja: + extends: + - .windows_ninja + - .windows_vcvarsall_vs2022_x64 + + variables: + CMAKE_CONFIGURATION: windows_intelclassic_ninja + +.windows_inteloneapi_ninja: + extends: + - .windows_ninja + - .windows_vcvarsall_vs2022_x64 + + variables: + CMAKE_CONFIGURATION: windows_inteloneapi_ninja + .windows_openwatcom: extends: .windows diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el index 7590ee3c1b..6bd23bf388 100644 --- a/Auxiliary/cmake-mode.el +++ b/Auxiliary/cmake-mode.el @@ -372,7 +372,7 @@ optional argument topic will be appended to the argument list." (interactive "s") (let* ((bufname (if buffer buffer (concat "*CMake" type (if topic "-") topic "*"))) (buffer (if (get-buffer bufname) (get-buffer bufname) (generate-new-buffer bufname))) - (command (concat cmake-mode-cmake-executable " " type " " (shell-quote-argument topic))) + (command (concat cmake-mode-cmake-executable " " type " " (if topic (shell-quote-argument topic) topic))) ;; Turn of resizing of mini-windows for shell-command. (resize-mini-windows nil) ) @@ -391,7 +391,7 @@ optional argument topic will be appended to the argument list." (interactive "s") (let* ((bufname (if buffer buffer (concat "*CMake" type (if topic "-") topic "*"))) (buffer (if (get-buffer bufname) (get-buffer bufname) (generate-new-buffer bufname))) - (command (concat cmake-mode-cmake-executable " " type " " (shell-quote-argument topic))) + (command (concat cmake-mode-cmake-executable " " type " " (if topic (shell-quote-argument topic) topic))) ;; Turn of resizing of mini-windows for shell-command. (resize-mini-windows nil) ) diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index d6b5b1946d..aefdcee281 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -73,6 +73,7 @@ syn keyword cmakeProperty contained \ AUTOGEN_ORIGIN_DEPENDS \ AUTOGEN_PARALLEL \ AUTOGEN_SOURCE_GROUP + \ AUTOGEN_USE_SYSTEM_INCLUDE \ AUTOGEN_TARGETS_FOLDER \ AUTOGEN_TARGET_DEPENDS \ AUTOMOC @@ -683,6 +684,7 @@ syn keyword cmakeVariable contained \ CMAKE_ASM_VISIBILITY_PRESET \ CMAKE_AUTOGEN_ORIGIN_DEPENDS \ CMAKE_AUTOGEN_PARALLEL + \ CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE \ CMAKE_AUTOGEN_VERBOSE \ CMAKE_AUTOMOC \ CMAKE_AUTOMOC_COMPILER_PREDEFINES @@ -2744,6 +2746,7 @@ syn keyword cmakeKWfile contained \ READ_SYMLINK \ REAL_PATH \ REGEX + \ RELATIVE \ RELATIVE_PATH \ RELEASE \ REMOVE diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index 21236fa427..fe26d2b9a5 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -132,6 +132,9 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: .. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace:: |prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_PREFIX_PATH` +.. |ENV_CMAKE_PREFIX_PATH_XXX_SUBDIR| replace:: + |prefix_XXX_SUBDIR| for each ``<prefix>`` in :envvar:`CMAKE_PREFIX_PATH` + .. |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR| replace:: |prefix_XXX_SUBDIR| for each ``<prefix>/[s]bin`` in ``PATH``, and |entry_XXX_SUBDIR| for other entries in ``PATH`` @@ -194,9 +197,9 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` to ``FALSE``. - * |CMAKE_PREFIX_PATH_XXX| - * |CMAKE_XXX_PATH| - * |CMAKE_XXX_MAC_PATH| + * |ENV_CMAKE_PREFIX_PATH_XXX| + * |ENV_CMAKE_XXX_PATH| + * |ENV_CMAKE_XXX_MAC_PATH| 4. Search the paths specified by the ``HINTS`` option. These should be paths computed by system introspection, such as a diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst index c5c40149de..9f89f5251d 100644 --- a/Help/command/find_file.rst +++ b/Help/command/find_file.rst @@ -19,6 +19,13 @@ find_file .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_INCLUDE_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH` +.. |ENV_CMAKE_PREFIX_PATH_XXX| replace:: + ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, + and |ENV_CMAKE_PREFIX_PATH_XXX_SUBDIR| +.. |ENV_CMAKE_XXX_PATH| replace:: :envvar:`CMAKE_INCLUDE_PATH` +.. |ENV_CMAKE_XXX_MAC_PATH| replace:: :envvar:`CMAKE_FRAMEWORK_PATH` + + .. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``INCLUDE`` and ``PATH``. .. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts: diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst index c237e7f0d3..99e36a49b6 100644 --- a/Help/command/find_library.rst +++ b/Help/command/find_library.rst @@ -19,6 +19,12 @@ find_library .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_LIBRARY_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH` +.. |ENV_CMAKE_PREFIX_PATH_XXX| replace:: + ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, + and |ENV_CMAKE_PREFIX_PATH_XXX_SUBDIR| +.. |ENV_CMAKE_XXX_PATH| replace:: :envvar:`CMAKE_LIBRARY_PATH` +.. |ENV_CMAKE_XXX_MAC_PATH| replace:: :envvar:`CMAKE_FRAMEWORK_PATH` + .. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``LIB`` and ``PATH``. .. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts: diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index b82088eaa0..b0b6fe1112 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -418,8 +418,8 @@ enabled. * ``<PackageName>_DIR`` * :envvar:`CMAKE_PREFIX_PATH` - * ``CMAKE_FRAMEWORK_PATH`` - * ``CMAKE_APPBUNDLE_PATH`` + * :envvar:`CMAKE_FRAMEWORK_PATH` + * :envvar:`CMAKE_APPBUNDLE_PATH` 4. Search paths specified by the ``HINTS`` option. These should be paths computed by system introspection, such as a hint provided by the diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst index 1d7648d05c..f0522f6430 100644 --- a/Help/command/find_path.rst +++ b/Help/command/find_path.rst @@ -19,6 +19,12 @@ find_path .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_INCLUDE_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH` +.. |ENV_CMAKE_PREFIX_PATH_XXX| replace:: + ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, + and |ENV_CMAKE_PREFIX_PATH_XXX_SUBDIR| +.. |ENV_CMAKE_XXX_PATH| replace:: :envvar:`CMAKE_INCLUDE_PATH` +.. |ENV_CMAKE_XXX_MAC_PATH| replace:: :envvar:`CMAKE_FRAMEWORK_PATH` + .. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``INCLUDE`` and ``PATH``. .. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts: diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst index f4149be5ad..fe95a9a300 100644 --- a/Help/command/find_program.rst +++ b/Help/command/find_program.rst @@ -17,6 +17,11 @@ find_program .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_APPBUNDLE_PATH` +.. |ENV_CMAKE_PREFIX_PATH_XXX| replace:: + |ENV_CMAKE_PREFIX_PATH_XXX_SUBDIR| +.. |ENV_CMAKE_XXX_PATH| replace:: :envvar:`CMAKE_PROGRAM_PATH` +.. |ENV_CMAKE_XXX_MAC_PATH| replace:: :envvar:`CMAKE_APPBUNDLE_PATH` + .. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` itself. .. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts no extra search paths are included diff --git a/Help/command/list.rst b/Help/command/list.rst index 191003a700..0c7a562872 100644 --- a/Help/command/list.rst +++ b/Help/command/list.rst @@ -188,7 +188,7 @@ For more information on regular expressions look under .. versionadded:: 3.12 - Transforms the list by applying an action to all or, by specifying a + 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. @@ -205,42 +205,42 @@ For more information on regular expressions look under :command:`APPEND <string(APPEND)>`, :command:`PREPEND <string(PREPEND)>` Append, prepend specified value to each element of the list. - .. code-block:: cmake - - list(TRANSFORM <list> <APPEND|PREPEND> <value> ...) + .. signature:: + list(TRANSFORM <list> (APPEND|PREPEND) <value> ...) + :target: TRANSFORM_APPEND - :command:`TOUPPER <string(TOUPPER)>`, :command:`TOLOWER <string(TOLOWER)>` - Convert each element of the list to upper, lower characters. + :command:`TOLOWER <string(TOLOWER)>`, :command:`TOUPPER <string(TOUPPER)>` + Convert each element of the list to lower, upper characters. - .. code-block:: cmake - - list(TRANSFORM <list> <TOLOWER|TOUPPER> ...) + .. signature:: + list(TRANSFORM <list> (TOLOWER|TOUPPER) ...) + :target: TRANSFORM_TOLOWER :command:`STRIP <string(STRIP)>` Remove leading and trailing spaces from each element of the list. - .. code-block:: cmake - + .. signature:: list(TRANSFORM <list> STRIP ...) + :target: TRANSFORM_STRIP :command:`GENEX_STRIP <string(GENEX_STRIP)>` Strip any :manual:`generator expressions <cmake-generator-expressions(7)>` from each element of the list. - .. code-block:: cmake - + .. signature:: list(TRANSFORM <list> GENEX_STRIP ...) + :target: TRANSFORM_GENEX_STRIP :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 - + .. signature:: list(TRANSFORM <list> REPLACE <regular_expression> <replace_expression> ...) + :target: TRANSFORM_REPLACE ``<SELECTOR>`` determines which elements of the list will be transformed. Only one type of selector can be specified at a time. diff --git a/Help/command/string.rst b/Help/command/string.rst index e226aa1a48..0e69b27ebc 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -576,6 +576,9 @@ Functionality for querying a JSON string. Set an element in ``<json-string>`` at the location given by the list of ``<member|index>`` arguments to ``<value>``. The contents of ``<value>`` should be valid JSON. + If ``<json-string>`` is an array, ``<value>`` can be appended to the end of + the array by using a number greater or equal to the array length as the + ``<member|index>`` argument. .. signature:: string(JSON <out-var> [ERROR_VARIABLE <error-var>] diff --git a/Help/cpack_gen/innosetup.rst b/Help/cpack_gen/innosetup.rst new file mode 100644 index 0000000000..f48e7f56c6 --- /dev/null +++ b/Help/cpack_gen/innosetup.rst @@ -0,0 +1,420 @@ +CPack Inno Setup Generator +-------------------------- + +.. versionadded:: 3.27 + +Inno Setup is a free installer for Windows programs by Jordan Russell and +Martijn Laan (https://jrsoftware.org/isinfo.php). + +This documentation explains Inno Setup generator specific options. + +The generator provides a lot of options like components. Unfortunately, not +all features (e.g. component dependencies) are currently supported by +Inno Setup and they're ignored by the generator for now. + +CPack requires Inno Setup 6 or greater and only works on Windows. + +Variables specific to CPack Inno Setup generator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can use the following variables to change the behavior of the CPack +``INNOSETUP`` generator: + + +General +""""""" + +None of the following variables is required to be set for the Inno Setup +generator to work. If a variable is marked as mandatory below but not set, +its default value is taken. + +The variables can also contain Inno Setup constants like ``{app}``. Please +refer to the documentation of Inno Setup for more information. + +If you're asked to provide the path to any file, you can always give an +absolute path or in most cases the relative path from the top-level directory +where all files being installed by an :command:`install` instruction reside. + +CPack tries to escape quotes and other special characters for you. However, +using special characters could cause problems. + +The following variable simplifies the usage of Inno Setup in CMake: + +.. variable:: CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT + + Inno Setup only uses ``yes`` or ``no`` as boolean formats meanwhile CMake + uses a lot of alternative formats like ``ON`` or ``OFF``. Having this option + turned on enables an automatic conversion. + + Consider the following example: + + .. code-block:: cmake + + set(CMAKE_INNOSETUP_SETUP_AllowNoIcons OFF) + + If this option is turned on, the following line will be created in the output + script: ``AllowNoIcons=no``. + Else, the following erroneous line will be created: ``AllowNoIcons=OFF`` + + The conversion is enabled in every Inno Setup specific variable. + + :Mandatory: Yes + :Default: ``ON`` + + +Setup Specific Variables +"""""""""""""""""""""""" + +.. variable:: CPACK_INNOSETUP_ARCHITECTURE + + One of ``x86``, ``x64``, ``arm64`` or ``ia64``. This variable specifies the + target architecture of the installer. This also affects the Program Files + folder or registry keys being used. + + CPack tries to determine the correct value with a try compile (see + :variable:`CMAKE_SIZEOF_VOID_P`), but this option can be manually specified + too (especially when using ``ia64`` or cross-platform compilation). + + :Mandatory: Yes + :Default: Either ``x86`` or ``x64`` depending on the results of the try-compile + +.. variable:: CPACK_INNOSETUP_INSTALL_ROOT + + If you don't want the installer to create the installation directory under + Program Files, you've to specify the installation root here. + + The full directory of the installation will be: + ``${CPACK_INNOSETUP_INSTALL_ROOT}/${CPACK_PACKAGE_INSTALL_DIRECTORY}``. + + :Mandatory: Yes + :Default: ``{autopf}`` + +.. variable:: CPACK_INNOSETUP_ALLOW_CUSTOM_DIRECTORY + + If turned on, the installer allows the user to change the installation + directory providing an extra wizard page. + + :Mandatory: Yes + :Default: ``ON`` + +.. variable:: CPACK_INNOSETUP_PROGRAM_MENU_FOLDER + + The initial name of the start menu folder being created. + + If this variable is set to ``.``, then no separate folder is created, + application shortcuts will appear in the top-level start menu folder. + + :Mandatory: Yes + :Default: The value of :variable:`CPACK_PACKAGE_NAME` + +.. variable:: CPACK_INNOSETUP_LANGUAGES + + A :ref:`semicolon-separated list <CMake Language Lists>` of languages you want + Inno Setup to include. + + Currently available: ``armenian``, ``brazilianPortuguese``, ``bulgarian``, + ``catalan``, ``corsican``, ``czech``, ``danish``, ``dutch``, ``english``, + ``finnish``, ``french``, ``german``, ``hebrew``, ``icelandic``, ``italian``, + ``japanese``, ``norwegian``, ``polish``, ``portuguese``, ``russian``, + ``slovak``, ``slovenian``, ``spanish``, ``turkish`` and ``ukrainian``. + This list might differ depending on the version of Inno Setup. + + :Mandatory: Yes + :Default: ``english`` + +.. variable:: CPACK_INNOSETUP_IGNORE_LICENSE_PAGE + + If you don't specify a license file using + :variable:`CPACK_RESOURCE_FILE_LICENSE`, CPack uses a file for demonstration + purposes. If you want the installer to ignore license files at all, you can + enable this option. + + :Mandatory: Yes + :Default: ``OFF`` + +.. variable:: CPACK_INNOSETUP_IGNORE_README_PAGE + + If you don't specify a readme file using + :variable:`CPACK_RESOURCE_FILE_README`, CPack uses a file for demonstration + purposes. If you want the installer to ignore readme files at all, you can + enable this option. Make sure the option is disabled when using + a custom readme file. + + :Mandatory: Yes + :Default: ``ON`` + +.. variable:: CPACK_INNOSETUP_PASSWORD + + Enables password protection and file encryption with the given password. + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_USE_MODERN_WIZARD + + Enables the modern look and feel provided by Inno Setup. If this option is + turned off, the classic style is used instead. Images and icon files are + also affected. + + :Mandatory: Yes + :Default: ``OFF`` because of compatibility reasons + +.. variable:: CPACK_INNOSETUP_ICON_FILE + + The path to a custom installer ``.ico`` file. + + Use :variable:`CPACK_PACKAGE_ICON` to customize the bitmap file being shown + in the wizard. + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_SETUP_<directive> + + This group allows adapting any of the ``[Setup]`` section directives provided + by Inno Setup where ``directive`` is its name. + + Here are some examples: + + .. code-block:: cmake + + set(CPACK_INNOSETUP_SETUP_WizardSmallImageFile "my_bitmap.bmp") + set(CPACK_INNOSETUP_SETUP_AllowNoIcons OFF) # This requires CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT to be on + + All of these variables have higher priority than the others. + Consider the following example: + + .. code-block:: cmake + + set(CPACK_INNOSETUP_SETUP_Password "admin") + set(CPACK_INNOSETUP_PASSWORD "secret") + + The password will be ``admin`` at the end because ``CPACK_INNOSETUP_PASSWORD`` + has less priority than ``CPACK_INNOSETUP_SETUP_Password``. + + :Mandatory: No + + +File Specific Variables +""""""""""""""""""""""" + +Although all files being installed by an :command:`install` instruction are +automatically processed and added to the installer, there are some variables +to customize the installation process. + +Before using executables (only ``.exe`` or ``.com``) in shortcuts +(e.g. :variable:`CPACK_CREATE_DESKTOP_LINKS`) or ``[Run]`` entries, you've to +add the raw file name (without path and extension) to +:variable:`CPACK_PACKAGE_EXECUTABLES` and create a start menu shortcut +for them. + +If you have two files with the same raw name (e.g. ``a/executable.exe`` and +``b/executable.com``), an entry in the section is created twice. This will +result in undefined behavior and is not recommended. + +.. variable:: CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS + + This variable should contain a + :ref:`semicolon-separated list <CMake Language Lists>` of pairs ``path``, + ``instruction`` and can be used to customize the install command being + automatically created for each file or directory. + + CPack creates the following Inno Setup instruction for every file... + + .. code-block:: + + Source: "absolute\path\to\my_file.txt"; DestDir: "{app}"; Flags: ignoreversion + + ...and the following line for every directory: + + .. code-block:: + + Name: "{app}\my_folder" + + You might want to change the destination directory or the flags of + ``my_file.txt``. Since we can also provide a relative path, the line you'd + like to have, is the following: + + .. code-block:: + + Source: "my_file.txt"; DestDir: "{userdocs}"; Flags: ignoreversion uninsneveruninstall + + You would do this by using ``my_file.txt`` as ``path`` and + ``Source: "my_file.txt"; DestDir: "{userdocs}"; Flags: ignoreversion uninsneveruninstall`` + as ``instruction``. + + You've to take care of the `escaping problem <https://cmake.org/cmake/help/book/mastering-cmake/chapter/Packaging%20With%20CPack.html#adding-custom-cpack-options>`_. + So the CMake command would be: + + .. code-block:: cmake + + set(CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS "my_file.txt;Source: \\\"my_file.txt\\\"\\; DestDir: \\\"{userdocs}\\\"\\; Flags: ignoreversion uninsneveruninstall") + + To improve readability, you should go around the escaping problem by using + :variable:`CPACK_VERBATIM_VARIABLES` or by placing the instruction into a + separate CPack project config file. + + If you customize the install instruction of a specific file, you lose the + connection to its component. To go around, manually add + ``Components: <component>``. You also need to add its shortcuts and ``[Run]`` + entries by yourself in a custom section, since the executable won't be found + anymore by :variable:`CPACK_PACKAGE_EXECUTABLES`. + + Here's another example (Note: You've to go around the escaping problem for + the example to work): + + .. code-block:: cmake + + set(CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS + "component1/my_folder" "Name: \"{userdocs}\\my_folder\"\; Components: component1" + "component2/my_folder2/my_file.txt" "Source: \"component2\\my_folder2\\my_file.txt\"\; DestDir: \"{app}\\my_folder2\\my_file.txt\"\; Flags: ignoreversion uninsneveruninstall\; Components: component2") + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_MENU_LINKS + + This variable should contain a + :ref:`semicolon-separated list <CMake Language Lists>` of pairs ``link``, + ``link name`` and can be used to add shortcuts into the start menu folder + beside those of the executables (see :variable:`CPACK_PACKAGE_EXECUTABLES`). + While ``link name`` is the label, ``link`` can be a URL or a path relative to + the installation directory. + + Here's an example: + + .. code-block:: cmake + + set(CPACK_INNOSETUP_MENU_LINKS + "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html" + "CMake Help" "https://cmake.org" "CMake Web Site") + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_CREATE_UNINSTALL_LINK + + If this option is turned on, a shortcut to the application's uninstaller is + automatically added to the start menu folder. + + :Mandatory: Yes + :Default: ``OFF`` + +.. variable:: CPACK_INNOSETUP_RUN_EXECUTABLES + + A :ref:`semicolon-separated list <CMake Language Lists>` of executables being + specified in :variable:`CPACK_PACKAGE_EXECUTABLES` which the user can run + when the installer finishes. + + They're internally added to the ``[Run]`` section. + + :Mandatory: No + + +Components Specific Variables +""""""""""""""""""""""""""""" + +The generator supports components and also downloaded components. However, +there are some features of components that aren't supported yet (especially +component dependencies). These variables are ignored for now. + +CPack will change a component's name in Inno Setup if it has a parent group +for technical reasons. Consider using ``group\component`` as component name in +Inno Setup scripts if you have the component ``component`` and its parent +group ``group``. + +Here are some additional variables for components: + +.. variable:: CPACK_INNOSETUP_<compName>_INSTALL_DIRECTORY + + If you don't want the component ``compName`` to be installed under ``{app}``, + you've to specify its installation directory here. + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_VERIFY_DOWNLOADS + + This option only affects downloaded components. + + If this option is turned on, the hashes of the downloaded archives are + calculated during compile and + download time. The installer will only proceed if they match. + + :Mandatory: Yes + :Default: ``ON`` + + +Compilation and Scripting Specific Variables +"""""""""""""""""""""""""""""""""""""""""""" + +.. variable:: CPACK_INNOSETUP_EXECUTABLE + + The filename of the Inno Setup Script Compiler command. + + :Mandatory: Yes + :Default: ``ISCC`` + +.. variable:: CPACK_INNOSETUP_EXECUTABLE_ARGUMENTS + + A :ref:`semicolon-separated list <CMake Language Lists>` of extra + command-line options for the Inno Setup Script Compiler command. + + For example: ``/Qp;/Smysigntool=$p`` + + Take care of the `escaping problem <https://cmake.org/cmake/help/book/mastering-cmake/chapter/Packaging%20With%20CPack.html#adding-custom-cpack-options>`_. + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_DEFINE_<macro> + + This group allows to add custom define directives as command-line options to + the Inno Setup Preprocessor command. Each entry emulates a + ``#define public <macro>`` directive. Its macro is accessible from anywhere + (``public``), so it can also be used in extra script files. + + Macro names must not contain any special characters. Refer to the Inno Setup + Preprocessor documentation for the detailed rules. + + Consider the following example: + + .. code-block:: cmake + + # The following line emulates: #define public MyMacro "Hello, World!" + set(CPACK_INNOSETUP_DEFINE_MyMacro "Hello, World!") + + At this point, you can use ``MyMacro`` anywhere. For example in the following + extra script: + + .. code-block:: + + AppComments={#emit "'My Macro' has the value: " + MyMacro} + + Take care of the `escaping problem <https://cmake.org/cmake/help/book/mastering-cmake/chapter/Packaging%20With%20CPack.html#adding-custom-cpack-options>`_. + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_EXTRA_SCRIPTS + + A :ref:`semicolon-separated list <CMake Language Lists>` of paths to + additional ``.iss`` script files to be processed. + + They're internally included at the top of the output script file using a + ``#include`` directive. + + You can add any section in your file to extend the installer (e.g. adding + additional tasks or registry keys). Prefer using + :variable:`CPACK_INNOSETUP_SETUP_<directive>` when extending the + ``[Setup]`` section. + + :Mandatory: No + +.. variable:: CPACK_INNOSETUP_CODE_FILES + + A :ref:`semicolon-separated list <CMake Language Lists>` of paths to + additional Pascal files to be processed. + + This variable is actually the same as + :variable:`CPACK_INNOSETUP_EXTRA_SCRIPTS`, except you don't have to + add ``[Code]`` at the top of your file. Never change the current section in + a code file. This will result in undefined behavior! Treat them as normal + Pascal scripts instead. + + Code files are included at the very bottom of the output script. + + :Mandatory: No diff --git a/Help/envvar/CMAKE_APPBUNDLE_PATH.rst b/Help/envvar/CMAKE_APPBUNDLE_PATH.rst new file mode 100644 index 0000000000..d80e08dcf7 --- /dev/null +++ b/Help/envvar/CMAKE_APPBUNDLE_PATH.rst @@ -0,0 +1,14 @@ +CMAKE_APPBUNDLE_PATH +-------------------- + +.. include:: ENV_VAR.txt + +The ``CMAKE_APPBUNDLE_PATH`` environment variable may be set to a list of +directories to be searched for macOS application bundles +by the :command:`find_program` and :command:`find_package` commands. + +This variable may hold a single directory or a list of directories separated +by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment +variable convention on those platforms). + +See also the :variable:`CMAKE_APPBUNDLE_PATH` CMake variable. diff --git a/Help/envvar/CMAKE_FRAMEWORK_PATH.rst b/Help/envvar/CMAKE_FRAMEWORK_PATH.rst new file mode 100644 index 0000000000..f543132dbc --- /dev/null +++ b/Help/envvar/CMAKE_FRAMEWORK_PATH.rst @@ -0,0 +1,15 @@ +CMAKE_FRAMEWORK_PATH +-------------------- + +.. include:: ENV_VAR.txt + +The ``CMAKE_FRAMEWORK_PATH`` environment variable may be set to a list of +directories to be searched for macOS frameworks by the :command:`find_library`, +:command:`find_package`, :command:`find_path` and :command:`find_file` commands. + + +This variable may hold a single directory or a list of directories separated +by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment +variable convention on those platforms). + +See also the :variable:`CMAKE_FRAMEWORK_PATH` CMake variable. diff --git a/Help/envvar/CMAKE_INCLUDE_PATH.rst b/Help/envvar/CMAKE_INCLUDE_PATH.rst new file mode 100644 index 0000000000..a42460d9d6 --- /dev/null +++ b/Help/envvar/CMAKE_INCLUDE_PATH.rst @@ -0,0 +1,13 @@ +CMAKE_INCLUDE_PATH +------------------ + +.. include:: ENV_VAR.txt + +The ``CMAKE_INCLUDE_PATH`` environment variable may be set to a list of +directories to be searched by the :command:`find_file` and :command:`find_path` commands. + +This variable may hold a single directory or a list of directories separated +by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment +variable convention on those platforms). + +See also the :variable:`CMAKE_INCLUDE_PATH` CMake variable. diff --git a/Help/envvar/CMAKE_LIBRARY_PATH.rst b/Help/envvar/CMAKE_LIBRARY_PATH.rst new file mode 100644 index 0000000000..a51100d2ea --- /dev/null +++ b/Help/envvar/CMAKE_LIBRARY_PATH.rst @@ -0,0 +1,13 @@ +CMAKE_LIBRARY_PATH +------------------ + +.. include:: ENV_VAR.txt + +The ``CMAKE_LIBRARY_PATH`` environment variable may be set to a list of +directories to be searched by the :command:`find_library` command. + +This variable may hold a single directory or a list of directories separated +by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment +variable convention on those platforms). + +See also the :variable:`CMAKE_LIBRARY_PATH` CMake variable. diff --git a/Help/envvar/CMAKE_PROGRAM_PATH.rst b/Help/envvar/CMAKE_PROGRAM_PATH.rst new file mode 100644 index 0000000000..bfc7a306ce --- /dev/null +++ b/Help/envvar/CMAKE_PROGRAM_PATH.rst @@ -0,0 +1,13 @@ +CMAKE_PROGRAM_PATH +------------------ + +.. include:: ENV_VAR.txt + +The ``CMAKE_PROGRAM_PATH`` environment variable may be set to a list of +directories to be searched by the :command:`find_program` command. + +This variable may hold a single directory or a list of directories separated +by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment +variable convention on those platforms). + +See also the :variable:`CMAKE_PROGRAM_PATH` CMake variable. diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index aba9f7ad4d..3dab97ff04 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -27,168 +27,7 @@ expressions are the ``0`` and ``1`` expressions. A ``$<0:...>`` results in the empty string, and ``<1:...>`` results in the content of ``...``. They can also be nested. -Exercise 1 - Setting the C++ Standard with Interface Libraries -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Before we use :manual:`generator expressions <cmake-generator-expressions(7)>` -let's refactor our existing code to use an ``INTERFACE`` library. We will -use that library in the next step to demonstrate a common use for -:manual:`generator expressions <cmake-generator-expressions(7)>`. - -Goal ----- - -Add an ``INTERFACE`` library target to specify the required C++ standard. - -Helpful Resources ------------------ - -* :command:`add_library` -* :command:`target_compile_features` -* :command:`target_link_libraries` - -Files to Edit -------------- - -* ``CMakeLists.txt`` -* ``MathFunctions/CMakeLists.txt`` - -Getting Started ---------------- - -In this exercise, we will refactor our code to use an ``INTERFACE`` library to -specify the C++ standard. - -The starting source code is provided in the ``Step4`` directory. In this -exercise, complete ``TODO 1`` through ``TODO 3``. - -Start by editing the top level ``CMakeLists.txt`` file. Construct an -``INTERFACE`` library target called ``tutorial_compiler_flags`` and -specify ``cxx_std_11`` as a target compiler feature. - -Modify ``CMakeLists.txt`` and ``MathFunctions/CMakeLists.txt`` so that all -targets have a :command:`target_link_libraries` call to -``tutorial_compiler_flags``. - -Build and Run -------------- - -Make a new directory called ``Step4_build``, run the :manual:`cmake <cmake(1)>` -executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project -and then build it with your chosen build tool or by using ``cmake --build .`` -from the build directory. - -Here's a refresher of what that looks like from the command line: - -.. code-block:: console - - mkdir Step4_build - cd Step4_build - cmake ../Step4 - cmake --build . - -Next, use the newly built ``Tutorial`` and verify that it is working as -expected. - -Solution --------- - -Let's update our code from the previous step to use interface libraries -to set our C++ requirements. - -To start, we need to remove the two :command:`set` calls on the variables -:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`. -The specific lines to remove are as follows: - -.. literalinclude:: Step4/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-CXX_STANDARD-variable-remove - :language: cmake - :start-after: # specify the C++ standard - :end-before: # TODO 6: Create helper variables - -Next, we need to create an interface library, ``tutorial_compiler_flags``. And -then use :command:`target_compile_features` to add the compiler feature -``cxx_std_11``. - - -.. raw:: html - - <details><summary>TODO 1: Click to show/hide answer</summary> - -.. literalinclude:: Step5/CMakeLists.txt - :caption: TODO 1: CMakeLists.txt - :name: CMakeLists.txt-cxx_std-feature - :language: cmake - :start-after: # specify the C++ standard - :end-before: # add compiler warning flags just - -.. raw:: html - - </details> - -Finally, with our interface library set up, we need to link our -executable ``Target``, our ``MathFunctions`` library, and our ``SqrtLibrary`` -library to our new -``tutorial_compiler_flags`` library. Respectively, the code will look like -this: - -.. raw:: html - - <details><summary>TODO 2: Click to show/hide answer</summary> - -.. literalinclude:: Step5/CMakeLists.txt - :caption: TODO 2: CMakeLists.txt - :name: CMakeLists.txt-target_link_libraries-step4 - :language: cmake - :start-after: add_executable(Tutorial tutorial.cxx) - :end-before: # add the binary tree to the search path for include file - -.. raw:: html - - </details> - -this: - -.. raw:: html - - <details><summary>TODO 3: Click to show/hide answer</summary> - -.. literalinclude:: Step5/MathFunctions/CMakeLists.txt - :caption: TODO 3: MathFunctions/CMakeLists.txt - :name: MathFunctions-CMakeLists.txt-target_link_libraries-step4 - :language: cmake - :start-after: # link our compiler flags interface library - :end-before: target_link_libraries(MathFunctions - -.. raw:: html - - </details> - -and this: - -.. raw:: html - - <details><summary>TODO 4: Click to show/hide answer</summary> - -.. literalinclude:: Step5/MathFunctions/CMakeLists.txt - :caption: TODO 4: MathFunctions/CMakeLists.txt - :name: MathFunctions-SqrtLibrary-target_link_libraries-step4 - :language: cmake - :start-after: target_link_libraries(SqrtLibrary - :end-before: endif() - -.. raw:: html - - </details> - - -With this, all of our code still requires C++ 11 to build. Notice -though that with this method, it gives us the ability to be specific about -which targets get specific requirements. In addition, we create a single -source of truth in our interface library. - -Exercise 2 - Adding Compiler Warning Flags with Generator Expressions +Exercise 1 - Adding Compiler Warning Flags with Generator Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A common usage of @@ -218,8 +57,8 @@ Files to Edit Getting Started --------------- -Start with the resulting files from Exercise 1. Complete ``TODO 5`` through -``TODO 8``. +Open the file ``Step4/CMakeLists.txt`` and complete ``TODO 1`` through +``TODO 4``. First, in the top level ``CMakeLists.txt`` file, we need to set the :command:`cmake_minimum_required` to ``3.15``. In this exercise we are going @@ -233,12 +72,16 @@ given a language and a set of compiler ids. Build and Run ------------- -Since we have our build directory already configured from Exercise 1, simply -rebuild our code by calling the following: +Make a new directory called ``Step4_build``, run the :manual:`cmake <cmake(1)>` +executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project +and then build it with your chosen build tool or by using ``cmake --build .`` +from the build directory. .. code-block:: console + mkdir Step4_build cd Step4_build + cmake ../Step4 cmake --build . Solution @@ -249,10 +92,10 @@ version ``3.15``: .. raw:: html - <details><summary>TODO 5: Click to show/hide answer</summary> + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step5/CMakeLists.txt - :caption: TODO 5: CMakeLists.txt + :caption: TODO 1: CMakeLists.txt :name: MathFunctions-CMakeLists.txt-minimum-required-step4 :language: cmake :end-before: # set the project name and version @@ -268,10 +111,10 @@ variables ``gcc_like_cxx`` and ``msvc_cxx`` as follows: .. raw:: html - <details><summary>TODO 6: Click to show/hide answer</summary> + <details><summary>TODO 2: Click to show/hide answer</summary> .. literalinclude:: Step5/CMakeLists.txt - :caption: TODO 6: CMakeLists.txt + :caption: TODO 2: CMakeLists.txt :name: CMakeLists.txt-compile_lang_and_id :language: cmake :start-after: # the BUILD_INTERFACE genex @@ -289,10 +132,10 @@ interface library. .. raw:: html - <details><summary>TODO 7: Click to show/hide answer</summary> + <details><summary>TODO 3: Click to show/hide answer</summary> .. code-block:: cmake - :caption: TODO 7: CMakeLists.txt + :caption: TODO 3: CMakeLists.txt :name: CMakeLists.txt-compile_flags target_compile_options(tutorial_compiler_flags INTERFACE @@ -311,10 +154,10 @@ condition. The resulting full code looks like the following: .. raw:: html - <details><summary>TODO 8: Click to show/hide answer</summary> + <details><summary>TODO 4: Click to show/hide answer</summary> .. literalinclude:: Step5/CMakeLists.txt - :caption: TODO 8: CMakeLists.txt + :caption: TODO 4: CMakeLists.txt :name: CMakeLists.txt-target_compile_options-genex :language: cmake :start-after: set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index 74b7496688..227306393e 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -100,7 +100,7 @@ follows: :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE :language: cmake :start-after: # to find MathFunctions.h - :end-before: option + :end-before: # should we use our own .. raw:: html @@ -108,24 +108,26 @@ follows: Now that we've specified usage requirements for ``MathFunctions`` we can safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level -``CMakeLists.txt``, here: +``CMakeLists.txt``. + +Remove this line: .. raw:: html <details><summary>TODO 2: Click to show/hide answer</summary> -.. literalinclude:: Step4/CMakeLists.txt +.. literalinclude:: Step3/CMakeLists.txt :caption: TODO 2: CMakeLists.txt :name: CMakeLists.txt-remove-EXTRA_INCLUDES :language: cmake - :start-after: # add the MathFunctions library - :end-before: # TODO 2: Link to tutorial_compiler_flags + :start-after: add_subdirectory(MathFunctions) + :end-before: # add the executable .. raw:: html </details> -And here: +And the lines: .. raw:: html @@ -141,7 +143,181 @@ And here: </details> +The remaining code looks like: + +.. raw:: html + + <details><summary>Click to show/hide the resulting code</summary> + +.. literalinclude:: Step4/CMakeLists.txt + :caption: Remaining code after removing EXTRA_INCLUDES + :name: CMakeLists.txt-after-removing-EXTRA_INCLUDES + :language: cmake + :start-after: add_subdirectory(MathFunctions) + +.. raw:: html + + </details> + + Notice that with this technique, the only thing our executable target does to use our library is call :command:`target_link_libraries` with the name of the library target. In larger projects, the classic method of specifying library dependencies manually becomes very complicated very quickly. + +Exercise 2 - Setting the C++ Standard with Interface Libraries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now that we have switched our code to a more modern approach, let's demonstrate +a modern technique to set properties to multiple targets. + +Let's refactor our existing code to use an ``INTERFACE`` library. We will +use that library in the next step to demonstrate a common use for +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +Goal +---- + +Add an ``INTERFACE`` library target to specify the required C++ standard. + +Helpful Resources +----------------- + +* :command:`add_library` +* :command:`target_compile_features` +* :command:`target_link_libraries` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``MathFunctions/CMakeLists.txt`` + +Getting Started +--------------- + +In this exercise, we will refactor our code to use an ``INTERFACE`` library to +specify the C++ standard. + +Start this exercise from what we left at the end of Step3 exercise 1. You will +have to complete ``TODO 4`` through ``TODO 7``. + +Start by editing the top level ``CMakeLists.txt`` file. Construct an +``INTERFACE`` library target called ``tutorial_compiler_flags`` and +specify ``cxx_std_11`` as a target compiler feature. + +Modify ``CMakeLists.txt`` and ``MathFunctions/CMakeLists.txt`` so that all +targets have a :command:`target_link_libraries` call to +``tutorial_compiler_flags``. + +Build and Run +------------- + +Since we have our build directory already configured from Exercise 1, simply +rebuild our code by calling the following: + +.. code-block:: console + + cd Step3_build + cmake --build . + +Next, use the newly built ``Tutorial`` and verify that it is working as +expected. + +Solution +-------- + +Let's update our code from the previous step to use interface libraries +to set our C++ requirements. + +To start, we need to remove the two :command:`set` calls on the variables +:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`. +The specific lines to remove are as follows: + +.. literalinclude:: Step3/CMakeLists.txt + :caption: CMakeLists.txt + :name: CMakeLists.txt-CXX_STANDARD-variable-remove + :language: cmake + :start-after: # specify the C++ standard + :end-before: # configure a header file + +Next, we need to create an interface library, ``tutorial_compiler_flags``. And +then use :command:`target_compile_features` to add the compiler feature +``cxx_std_11``. + + +.. raw:: html + + <details><summary>TODO 4: Click to show/hide answer</summary> + +.. literalinclude:: Step4/CMakeLists.txt + :caption: TODO 4: CMakeLists.txt + :name: CMakeLists.txt-cxx_std-feature + :language: cmake + :start-after: # specify the C++ standard + :end-before: # TODO 2: Create helper + +.. raw:: html + + </details> + +Finally, with our interface library set up, we need to link our +executable ``Target``, our ``MathFunctions`` library, and our ``SqrtLibrary`` +library to our new +``tutorial_compiler_flags`` library. Respectively, the code will look like +this: + +.. raw:: html + + <details><summary>TODO 5: Click to show/hide answer</summary> + +.. literalinclude:: Step4/CMakeLists.txt + :caption: TODO 5: CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries-step4 + :language: cmake + :start-after: add_executable(Tutorial tutorial.cxx) + :end-before: # add the binary tree to the search path for include file + +.. raw:: html + + </details> + +this: + +.. raw:: html + + <details><summary>TODO 6: Click to show/hide answer</summary> + +.. literalinclude:: Step4/MathFunctions/CMakeLists.txt + :caption: TODO 6: MathFunctions/CMakeLists.txt + :name: MathFunctions-CMakeLists.txt-target_link_libraries-step4 + :language: cmake + :start-after: # link our compiler flags interface library + :end-before: target_link_libraries(MathFunctions + +.. raw:: html + + </details> + +and this: + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> + +.. literalinclude:: Step4/MathFunctions/CMakeLists.txt + :caption: TODO 7: MathFunctions/CMakeLists.txt + :name: MathFunctions-SqrtLibrary-target_link_libraries-step4 + :language: cmake + :start-after: target_link_libraries(SqrtLibrary + :end-before: endif() + +.. raw:: html + + </details> + + +With this, all of our code still requires C++ 11 to build. Notice +though that with this method, it gives us the ability to be specific about +which targets get specific requirements. In addition, we create a single +source of truth in our interface library. diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index d606f305e8..694dfaf621 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -409,7 +409,7 @@ that has sources ``mysqrt.cxx``. :name: MathFunctions/CMakeLists.txt-add_library-SqrtLibrary :language: cmake :start-after: # library that just does sqrt - :end-before: target_link_libraries(MathFunctions + :end-before: # TODO 7: Link .. raw:: html @@ -426,7 +426,8 @@ enabled. :caption: TODO 13 : MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_link_libraries-SqrtLibrary :language: cmake - :lines: 16-18 + :start-after: to tutorial_compiler_flags + :end-before: endif() .. raw:: html diff --git a/Help/guide/tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt index f051826a7d..ac3e9f1ed7 100644 --- a/Help/guide/tutorial/Step3/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/CMakeLists.txt @@ -3,6 +3,12 @@ cmake_minimum_required(VERSION 3.10) # set the project name and version project(Tutorial VERSION 1.0) +# TODO 4: Replace the following code by: +# * Creating an interface library called tutorial_compiler_flags +# Hint: use add_library() with the INTERFACE signature +# * Add compiler feature cxx_std_11 to tutorial_compiler_flags +# Hint: Use target_compile_features() + # specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) @@ -20,6 +26,8 @@ list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions") # add the executable add_executable(Tutorial tutorial.cxx) +# TODO 5: Link Tutorial to tutorial_compiler_flags + target_link_libraries(Tutorial PUBLIC MathFunctions) # TODO 3: Remove use of EXTRA_INCLUDES diff --git a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt index 6f86ffef5b..0ffb9e1f5b 100644 --- a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt @@ -14,5 +14,9 @@ if (USE_MYMATH) mysqrt.cxx ) + # TODO 7: Link SqrtLibrary to tutorial_compiler_flags + target_link_libraries(MathFunctions PUBLIC SqrtLibrary) endif() + +# TODO 6: Link MathFunctions to tutorial_compiler_flags diff --git a/Help/guide/tutorial/Step4/CMakeLists.txt b/Help/guide/tutorial/Step4/CMakeLists.txt index 7531fb41ab..fba97669b4 100644 --- a/Help/guide/tutorial/Step4/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/CMakeLists.txt @@ -1,33 +1,27 @@ -# TODO 5: Update the minimum required version to 3.15 +# TODO 1: Update the minimum required version to 3.15 cmake_minimum_required(VERSION 3.10) # set the project name and version project(Tutorial VERSION 1.0) -# TODO 1: Replace the following code by: -# * Creating an interface library called tutorial_compiler_flags -# Hint: use add_library() with the INTERFACE signature -# * Add compiler feature cxx_std_11 to tutorial_compiler_flags -# Hint: Use target_compile_features() - # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) -# TODO 6: Create helper variables to determine which compiler we are using: +# TODO 2: Create helper variables to determine which compiler we are using: # * Create a new variable gcc_like_cxx that is true if we are using CXX and # any of the following compilers: ARMClang, AppleClang, Clang, GNU, LCC # * Create a new variable msvc_cxx that is true if we are using CXX and MSVC # Hint: Use set() and COMPILE_LANG_AND_ID -# TODO 7: Add warning flag compile options to the interface library +# TODO 3: Add warning flag compile options to the interface library # tutorial_compiler_flags. # * For gcc_like_cxx, add flags -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused # * For msvc_cxx, add flags -W3 # Hint: Use target_compile_options() -# TODO 8: With nested generator expressions, only use the flags for the +# TODO 4: With nested generator expressions, only use the flags for the # build-tree # Hint: Use BUILD_INTERFACE @@ -41,9 +35,7 @@ add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -# TODO 2: Link to tutorial_compiler_flags - -target_link_libraries(Tutorial PUBLIC MathFunctions) +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt index ffab4f0a80..48561eb23b 100644 --- a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt @@ -17,9 +17,10 @@ if (USE_MYMATH) mysqrt.cxx ) - # TODO 4: Link to tutorial_compiler_flags - + # link our compiler flags interface library + target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags) target_link_libraries(MathFunctions PUBLIC SqrtLibrary) endif() -# TODO 3: Link to tutorial_compiler_flags +# link our compiler flags interface library +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index 1f0c9111aa..f7ae94d339 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -20,8 +20,13 @@ Environment Variables that Change Behavior .. toctree:: :maxdepth: 1 + /envvar/CMAKE_APPBUNDLE_PATH + /envvar/CMAKE_FRAMEWORK_PATH + /envvar/CMAKE_INCLUDE_PATH + /envvar/CMAKE_LIBRARY_PATH /envvar/CMAKE_MAXIMUM_RECURSION_DEPTH /envvar/CMAKE_PREFIX_PATH + /envvar/CMAKE_PROGRAM_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 da7df70fa2..473e8d7cf1 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -104,6 +104,17 @@ improved further like so: VERBATIM ) +Finally, the above example can be expressed in a more simple and robust way +using an alternate generator expression: + +.. code-block:: cmake + + add_custom_target(run_some_tool + COMMAND some_tool "$<LIST:TRANSFORM,$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>,PREPEND,-I>" + COMMAND_EXPAND_LISTS + VERBATIM + ) + A common mistake is to try to split a generator expression across multiple lines with indenting: @@ -318,6 +329,15 @@ String Transformations List Expressions ---------------- +Most of the expressions in this section are closely associated with the +:command:`list` command, providing the same capabilities, but in +the form of a generator expression. + +.. _GenEx List Comparisons: + +List Comparisons +^^^^^^^^^^^^^^^^ + .. genex:: $<IN_LIST:string,list> .. versionadded:: 3.12 @@ -325,9 +345,186 @@ List Expressions ``1`` if ``string`` is an item in the semicolon-separated ``list``, else ``0``. It uses case-sensitive comparisons. -.. genex:: $<JOIN:list,string> +.. _GenEx List Queries: + +List Queries +^^^^^^^^^^^^ + +.. genex:: $<LIST:LENGTH,list> + + .. versionadded:: 3.27 + + Returns the list's length. + +.. genex:: $<LIST:GET,list,index,...> + + .. versionadded:: 3.27 + + Returns the list of elements specified by indices from the list. + +.. genex:: $<LIST:SUBLIST,list,begin,length> + + .. versionadded:: 3.27 + + 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. + +.. genex:: $<LIST:FIND,list,value> + + .. versionadded:: 3.27 + + Returns the index of the element specified in the list or -1 if it wasn't + found. + +.. _GenEx List Transformations: + +List Transformations +^^^^^^^^^^^^^^^^^^^^ + +.. genex:: $<LIST:JOIN,list,glue> + + .. versionadded:: 3.27 + + Returns a string which joins the list with the content of the ``glue`` string + inserted between each item. + +.. genex:: $<LIST:APPEND,list,element,...> + + .. versionadded:: 3.27 + + Returns a list with the elements appended. + +.. genex:: $<LIST:PREPEND,list,element,...> + + .. versionadded:: 3.27 + + Returns a list with the elements inserted at the beginning of the list. + +.. genex:: $<LIST:INSERT,list,index,element,...> + + .. versionadded:: 3.27 + + Returns a list with the elements inserted at 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. + +.. genex:: $<LIST:POP_BACK,list> + + .. versionadded:: 3.27 + + Returns a list with the last element was removed. + +.. genex:: $<LIST:POP_FRONT,list> + + .. versionadded:: 3.27 + + Returns a list with the first element was removed. + +.. genex:: $<LIST:REMOVE_ITEM,list,value,...> + + .. versionadded:: 3.27 + + Returns a list with all instances of the given values were removed. + +.. genex:: $<LIST:REMOVE_AT,list,index,...> + + .. versionadded:: 3.27 - Joins the list with the content of ``string`` inserted between each item. + Returns a list with all values at given indices were removed. + +.. genex:: $<LIST:REMOVE_DUPLICATES,list> + + .. versionadded:: 3.27 + + Returns a list where duplicated items were removed. The relative order of + items is preserved, but if duplicates are encountered, only the first + instance is preserved. + +.. genex:: $<LIST:FILTER,list,INCLUDE|EXCLUDE,regex> + + .. versionadded:: 3.27 + + Returns a list with the items that match the regular expression ``regex`` + were included or removed. + +.. genex:: $<LIST:TRANSFORM,list,ACTION[,SELECTOR]> + + .. versionadded:: 3.27 + + Returns the list transformed by applying an ``ACTION`` to all or, by + specifying a ``SELECTOR``, to the selected elements of the list. + + .. 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. + + ``ACTION`` specifies the action to apply to the elements of the list. + The actions have exactly the same semantics as of the + :command:`list(TRANSFORM)` command. ``ACTION`` must be one of the following: + + :command:`APPEND <list(TRANSFORM_APPEND)>`, :command:`PREPEND <list(TRANSFORM_APPEND)>` + Append, prepend specified value to each element of the list. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,(APPEND|PREPEND),value[,SELECTOR]> + + :command:`TOLOWER <list(TRANSFORM_TOLOWER)>`, :command:`TOUPPER <list(TRANSFORM_TOLOWER)>` + Convert each element of the list to lower, upper characters. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,(TOLOWER|TOUPPER)[,SELECTOR]> + + :command:`STRIP <list(TRANSFORM_STRIP)>` + Remove leading and trailing spaces from each element of the list. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,STRIP[,SELECTOR]> + + :command:`REPLACE <list(TRANSFORM_REPLACE)>`: + Match the regular expression as many times as possible and substitute + the replacement expression for the match for each element of the list. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,REPLACE,regular_expression,replace_expression[,SELECTOR]> + + ``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. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,ACTION,AT,index[,index...]> + + ``FOR`` + Specify a range with, optionally, an increment used to iterate over the + range. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,ACTION,FOR,start,stop[,step]> + + ``REGEX`` + Specify a regular expression. + Only elements matching the regular expression will be transformed. + + .. code-block:: cmake + + $<LIST:TRANSFORM,list,ACTION,REGEX,regular_expression> + +.. genex:: $<JOIN:list,glue> + + Joins the list with the content of the ``glue`` string inserted between each + item. .. genex:: $<REMOVE_DUPLICATES:list> @@ -344,6 +541,69 @@ List Expressions Includes or removes items from ``list`` that match the regular expression ``regex``. +.. _GenEx List Ordering: + +List Ordering +^^^^^^^^^^^^^ + +.. genex:: $<LIST:REVERSE,list> + + .. versionadded:: 3.27 + + Returns the list with the elements in reverse order. + +.. genex:: $<LIST:SORT,list[,(COMPARE:option|CASE:option|ORDER:option)]...> + + .. versionadded:: 3.27 + + Returns the list sorted according the specified options. + + Use one of the ``COMPARE`` options to select the comparison method + for sorting: + + ``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. + + Use one of the ``CASE`` options to select a case sensitive or case + insensitive sort mode: + + ``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, one of the ``ORDER`` options can be 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. + + This is an error to specify multiple times the same option. Various options + can be specified in any order: + + .. code-block:: cmake + + $<LIST:SORT,list,CASE:SENSITIVE,COMPARE:STRING,ORDER:DESCENDING> + Path Expressions ---------------- diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 8c7189a72b..7c488060b9 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,8 @@ Policies Introduced by CMake 3.27 .. toctree:: :maxdepth: 1 + CMP0151: AUTOMOC include directory is a system include directory by default. </policy/CMP0151> + CMP0150: ExternalProject_Add and FetchContent_Declare treat relative git repository paths as being relative to parent project's remote. </policy/CMP0150> CMP0149: Visual Studio generators select latest Windows SDK by default. </policy/CMP0149> CMP0148: The FindPythonInterp and FindPythonLibs modules are removed. </policy/CMP0148> CMP0147: Visual Studio generators build custom commands in parallel. </policy/CMP0147> diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 7794e45ce5..e2366da0ac 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -133,6 +133,9 @@ Files directly or indirectly included from ``CMakePresets.json`` should be guaranteed to be provided by the project. ``CMakeUserPresets.json`` may include files from anywhere. +Starting from version ``7``, the ``include`` field supports +`macro expansion`_, but only ``$penv{}`` macro expansion. + Configure Preset ^^^^^^^^^^^^^^^^ @@ -1057,6 +1060,12 @@ fields: a workflow preset may have the same name as a configure, build, test, or package preset. +``vendor`` + An optional map containing vendor-specific information. CMake does not + interpret the contents of this field except to verify that it is a map + if it does exist. However, it should follow the same conventions as the + root-level ``vendor`` field. + ``displayName`` An optional string with a human-friendly name of the preset. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index c0e2ee2bdc..8ee5573149 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -133,6 +133,7 @@ Properties on Targets /prop_tgt/AUTOGEN_ORIGIN_DEPENDS /prop_tgt/AUTOGEN_PARALLEL /prop_tgt/AUTOGEN_TARGET_DEPENDS + /prop_tgt/AUTOGEN_USE_SYSTEM_INCLUDE /prop_tgt/AUTOMOC /prop_tgt/AUTOMOC_COMPILER_PREDEFINES /prop_tgt/AUTOMOC_DEPEND_FILTERS diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index f3212de4df..fa7a90fd8e 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -397,6 +397,7 @@ Variables that Control the Build /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS /variable/CMAKE_AUTOGEN_PARALLEL + /variable/CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE /variable/CMAKE_AUTOGEN_VERBOSE /variable/CMAKE_AUTOMOC /variable/CMAKE_AUTOMOC_COMPILER_PREDEFINES @@ -479,6 +480,7 @@ Variables that Control the Build /variable/CMAKE_LIBRARY_PATH_FLAG /variable/CMAKE_LINK_DEF_FILE_FLAG /variable/CMAKE_LINK_DEPENDS_NO_SHARED + /variable/CMAKE_LINK_DEPENDS_USE_LINKER /variable/CMAKE_LINK_GROUP_USING_FEATURE /variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED /variable/CMAKE_LINK_INTERFACE_LIBRARIES @@ -535,6 +537,10 @@ Variables that Control the Build /variable/CMAKE_USE_RELATIVE_PATHS /variable/CMAKE_VERIFY_INTERFACE_HEADER_SETS /variable/CMAKE_VISIBILITY_INLINES_HIDDEN + /variable/CMAKE_VS_DEBUGGER_COMMAND + /variable/CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS + /variable/CMAKE_VS_DEBUGGER_ENVIRONMENT + /variable/CMAKE_VS_DEBUGGER_WORKING_DIRECTORY /variable/CMAKE_VS_GLOBALS /variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD /variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD diff --git a/Help/manual/cpack-generators.7.rst b/Help/manual/cpack-generators.7.rst index ade9149c18..abb291b46e 100644 --- a/Help/manual/cpack-generators.7.rst +++ b/Help/manual/cpack-generators.7.rst @@ -20,6 +20,7 @@ Generators /cpack_gen/dmg /cpack_gen/external /cpack_gen/freebsd + /cpack_gen/innosetup /cpack_gen/ifw /cpack_gen/nsis /cpack_gen/nuget diff --git a/Help/policy/CMP0105.rst b/Help/policy/CMP0105.rst index 097a59abb8..aadc8d6ee6 100644 --- a/Help/policy/CMP0105.rst +++ b/Help/policy/CMP0105.rst @@ -8,12 +8,13 @@ properties are now used for the device link step. In CMake 3.17 and below, link options are not used by the device link step. -The ``OLD`` behavior for this policy is to ignore the link options. +The ``OLD`` behavior for this policy is to ignore the link options during the +device link step. The ``NEW`` behavior of this policy is to use the link options during the device link step. -This policy was introduced in CMake version 3.17. Use the +This policy was introduced in CMake version 3.18. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. Unlike many policies, CMake version |release| does *not* warn when this policy is not set and simply uses ``OLD`` behavior. diff --git a/Help/policy/CMP0150.rst b/Help/policy/CMP0150.rst new file mode 100644 index 0000000000..fe646d98f4 --- /dev/null +++ b/Help/policy/CMP0150.rst @@ -0,0 +1,39 @@ +CMP0150 +------- + +.. versionadded:: 3.27 + +:command:`ExternalProject_Add` and :command:`FetchContent_Declare` commands +treat relative ``GIT_REPOSITORY`` paths as being relative to the parent +project's remote. + +Earlier versions of these commands always treated relative paths in +``GIT_REPOSITORY`` as local paths, but the base directory it was treated +as relative to was both undocumented and unintuitive. The ``OLD`` behavior +for this policy is to interpret relative paths used for ``GIT_REPOSITORY`` +as local paths relative to the following: + +* The parent directory of ``SOURCE_DIR`` for :command:`ExternalProject_Add`. +* ``FETCHCONTENT_BASE_DIR`` for :command:`FetchContent_Declare`. + +The ``NEW`` behavior is to determine the remote from the parent project and +interpret the path relative to that remote. The value of +:variable:`CMAKE_CURRENT_SOURCE_DIR` when :command:`ExternalProject_Add` or +:command:`FetchContent_Declare` is called determines the parent project. +The remote is selected according to the following (the first match is used): + +* If the parent project is checked out on a branch with an upstream remote + defined, use that remote. +* If only one remote is defined, use that remote. +* If multiple remotes are defined and one of them is named ``origin``, use + ``origin``'s remote but also issue a warning. + +If an appropriate remote cannot be determined from the above, a fatal error +will be raised. + +This policy was introduced in CMake version 3.27. CMake version |release| +warns when a relative path is encountered and the policy is not set, +falling back to using ``OLD`` behavior. Use the :command:`cmake_policy` +command to set it to ``OLD`` or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/policy/CMP0151.rst b/Help/policy/CMP0151.rst new file mode 100644 index 0000000000..c12f595f16 --- /dev/null +++ b/Help/policy/CMP0151.rst @@ -0,0 +1,28 @@ +CMP0151 +------- + +.. versionadded:: 3.27 + +AUTOMOC include directory is a system include directory by default. + +Headers generated for :ref:`Qt AUTOMOC` are placed in target-specific include +directories. CMake 3.26 and older added these as normal include directories. +CMake 3.27 and newer prefer to add them as system include directories. +This policy provides compatibility for projects that have not been updated +to expect this. + +If the :prop_tgt:`AUTOGEN_USE_SYSTEM_INCLUDE` target property is set, +perhaps via the :variable:`CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE` variable, +then its value is used regardless of the setting of this policy. + +The ``OLD`` behavior for this policy is to add autogen include directory to +the target's include directories. +The ``NEW`` behavior for this policy is to add autogen include directory to +the target's system include directories. + +This policy was introduced in CMake version 3.27. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_tgt/AUTOGEN_USE_SYSTEM_INCLUDE.rst b/Help/prop_tgt/AUTOGEN_USE_SYSTEM_INCLUDE.rst new file mode 100644 index 0000000000..84212c861f --- /dev/null +++ b/Help/prop_tgt/AUTOGEN_USE_SYSTEM_INCLUDE.rst @@ -0,0 +1,17 @@ +AUTOGEN_USE_SYSTEM_INCLUDE +-------------------------- + +``AUTOGEN_USE_SYSTEM_INCLUDE`` is a boolean property that can be set +on a target to indicate that the autogen target include directory should +be added as a system include directory or normal include directory to the +target. + +If this property is not set, the autogen target include directory is added +as a system include directory by default. See policy :policy:`CMP0151`. + +See the :manual:`cmake-qt(7)` manual for more information on using CMake +with Qt. + +This property is initialized by the +:variable:`CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE` variable if it is set when +a target is created. diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst index 1e84c00850..5bf47a38a9 100644 --- a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst +++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst @@ -7,7 +7,9 @@ Sets the local debugger command for Visual Studio C++ targets. The property value may use :manual:`generator expressions <cmake-generator-expressions(7)>`. This is defined in ``<LocalDebuggerCommand>`` in the Visual Studio -project file. +project file. This property is initialized by the value of the variable +:variable:`CMAKE_VS_DEBUGGER_COMMAND` if it is set when a target is +created. This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst index e54e140b65..4b9dff7155 100644 --- a/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst +++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst @@ -7,7 +7,9 @@ Sets the local debugger command line arguments for Visual Studio C++ targets. The property value may use :manual:`generator expressions <cmake-generator-expressions(7)>`. This is defined in ``<LocalDebuggerCommandArguments>`` in the Visual Studio -project file. +project file. This property is initialized by the value of the variable +:variable:`CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS` if it is set when a target is +created. This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst b/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst index 60bc2f076e..8373dbb5c8 100644 --- a/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst +++ b/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst @@ -7,7 +7,9 @@ Sets the local debugger environment for Visual Studio C++ targets. The property value may use :manual:`generator expressions <cmake-generator-expressions(7)>`. This is defined in ``<LocalDebuggerEnvironment>`` in the Visual Studio -project file. +project file. This property is initialized by the value of the variable +:variable:`CMAKE_VS_DEBUGGER_ENVIRONMENT` if it is set when a target is +created. This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst index f9ce7aa367..39420475bd 100644 --- a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst +++ b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst @@ -7,7 +7,9 @@ Sets the local debugger working directory for Visual Studio C++ targets. The property value may use :manual:`generator expressions <cmake-generator-expressions(7)>`. This is defined in ``<LocalDebuggerWorkingDirectory>`` in the Visual Studio -project file. +project file. This property is initialized by the value of the variable +:variable:`CMAKE_VS_DEBUGGER_WORKING_DIRECTORY` if it is set when a target is +created. This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/release/dev/ExternalProject-FetchContent-relative-git-remotes.rst b/Help/release/dev/ExternalProject-FetchContent-relative-git-remotes.rst new file mode 100644 index 0000000000..d467620a39 --- /dev/null +++ b/Help/release/dev/ExternalProject-FetchContent-relative-git-remotes.rst @@ -0,0 +1,7 @@ +ExternalProject-FetchContent-Relative-git-remotes +------------------------------------------------- + +* The :module:`ExternalProject` and :module:`FetchContent` modules + now resolve relative `GIT_REPOSITORY` paths as relative to the + parent project's remote, not as a relative local file system path. + See :policy:`CMP0150`. diff --git a/Help/release/dev/FindDoxygen-custom-config-file.rst b/Help/release/dev/FindDoxygen-custom-config-file.rst new file mode 100644 index 0000000000..badc26e35b --- /dev/null +++ b/Help/release/dev/FindDoxygen-custom-config-file.rst @@ -0,0 +1,5 @@ +FindDoxygen-custom-config-file +------------------------------ + +* The :module:`FindDoxygen` module's ``doxygen_add_docs`` command gained + a ``CONFIG_FILE`` option to specify a custom doxygen configuration file. diff --git a/Help/release/dev/GenEx-LIST.rst b/Help/release/dev/GenEx-LIST.rst new file mode 100644 index 0000000000..f65a092db9 --- /dev/null +++ b/Help/release/dev/GenEx-LIST.rst @@ -0,0 +1,4 @@ +GenEx-LIST +---------- + +* The :genex:`LIST` generator expression was added to manage lists. diff --git a/Help/release/dev/autogen-system-include.rst b/Help/release/dev/autogen-system-include.rst new file mode 100644 index 0000000000..aea81be167 --- /dev/null +++ b/Help/release/dev/autogen-system-include.rst @@ -0,0 +1,7 @@ +autogen-system-include +---------------------- + +* The :prop_tgt:`AUTOGEN_USE_SYSTEM_INCLUDE` target property and + corresponding :variable:`CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE` were + added to explicitly control whether autogen headers are + considered system headers. diff --git a/Help/release/dev/cpack-innosetup.rst b/Help/release/dev/cpack-innosetup.rst new file mode 100644 index 0000000000..a9f8e8e331 --- /dev/null +++ b/Help/release/dev/cpack-innosetup.rst @@ -0,0 +1,12 @@ +cpack-innosetup +--------------- + +* The :cpack_gen:`CPack Inno Setup Generator` was added to package using + Inno Setup. + + The new generator adds: + + * A lot of options to customize the Inno Setup installer (e.g. custom + installation rules) + * Start menu and desktop shortcuts + * Components (and also downloaded components) diff --git a/Help/release/dev/preset-includes-macro-expansion.rst b/Help/release/dev/preset-includes-macro-expansion.rst new file mode 100644 index 0000000000..e1f00302a2 --- /dev/null +++ b/Help/release/dev/preset-includes-macro-expansion.rst @@ -0,0 +1,7 @@ +preset-includes-macro-expansion +------------------------------- + +* :manual:`cmake-presets(7)` files now support schema version ``7``. + +* :manual:`cmake-presets(7)` now supports ``$penv{}`` macro expansion + in ``include`` fields. diff --git a/Help/release/dev/use-linker-depfile.rst b/Help/release/dev/use-linker-depfile.rst new file mode 100644 index 0000000000..11237071f4 --- /dev/null +++ b/Help/release/dev/use-linker-depfile.rst @@ -0,0 +1,11 @@ +use-linker-depfile +------------------ + +* GNU (and GNU-compatible) linkers gained support for a ``--dependency-file`` + flag in GNU Binutils 2.35 and LLVM's LLD 12.0.0. The + :ref:`Makefile <Makefile Generators>` and :ref:`Ninja <Ninja Generators>` + generators will now add these flags so that files read by the linker will + cause a relink if they change (typically modified timestamps). + + This feature can be controlled by the variable + :variable:`CMAKE_LINK_DEPENDS_USE_LINKER`. diff --git a/Help/release/dev/vs-debugger-init.rst b/Help/release/dev/vs-debugger-init.rst new file mode 100644 index 0000000000..aa86839b66 --- /dev/null +++ b/Help/release/dev/vs-debugger-init.rst @@ -0,0 +1,8 @@ +vs-debugger-init +---------------- + +* Variables :variable:`CMAKE_VS_DEBUGGER_COMMAND`, + :variable:`CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS`, + :variable:`CMAKE_VS_DEBUGGER_ENVIRONMENT`, and + :variable:`CMAKE_VS_DEBUGGER_WORKING_DIRECTORY` were added to initialize + corresponding target properties. diff --git a/Help/variable/CMAKE_APPBUNDLE_PATH.rst b/Help/variable/CMAKE_APPBUNDLE_PATH.rst index 1c7ca51c2a..441ee8ebb2 100644 --- a/Help/variable/CMAKE_APPBUNDLE_PATH.rst +++ b/Help/variable/CMAKE_APPBUNDLE_PATH.rst @@ -4,3 +4,6 @@ CMAKE_APPBUNDLE_PATH :ref:`Semicolon-separated list <CMake Language Lists>` of directories specifying a search path for macOS application bundles used by the :command:`find_program`, and :command:`find_package` commands. + +There is also an environment variable :envvar:`CMAKE_APPBUNDLE_PATH`, which is used +as an additional list of search directories. diff --git a/Help/variable/CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE.rst b/Help/variable/CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE.rst new file mode 100644 index 0000000000..80ed8479ec --- /dev/null +++ b/Help/variable/CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE.rst @@ -0,0 +1,10 @@ +CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE +-------------------------------- + +.. versionadded:: 3.27 + +This variable is used to initialize the :prop_tgt:`AUTOGEN_USE_SYSTEM_INCLUDE` +property on all targets as they are created. See that target property for +additional information. + +By default ``CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE`` is unset. diff --git a/Help/variable/CMAKE_FRAMEWORK_PATH.rst b/Help/variable/CMAKE_FRAMEWORK_PATH.rst index 13ade4e5fc..8d62b028f7 100644 --- a/Help/variable/CMAKE_FRAMEWORK_PATH.rst +++ b/Help/variable/CMAKE_FRAMEWORK_PATH.rst @@ -5,3 +5,6 @@ CMAKE_FRAMEWORK_PATH for macOS frameworks used by the :command:`find_library`, :command:`find_package`, :command:`find_path`, and :command:`find_file` commands. + +There is also an environment variable :envvar:`CMAKE_FRAMEWORK_PATH`, which is used +as an additional list of search directories. diff --git a/Help/variable/CMAKE_INCLUDE_PATH.rst b/Help/variable/CMAKE_INCLUDE_PATH.rst index 4918e99602..3a4472a85f 100644 --- a/Help/variable/CMAKE_INCLUDE_PATH.rst +++ b/Help/variable/CMAKE_INCLUDE_PATH.rst @@ -3,5 +3,10 @@ CMAKE_INCLUDE_PATH :ref:`Semicolon-separated list <CMake Language Lists>` of directories specifying a search path for the :command:`find_file` and :command:`find_path` commands. By default it -is empty, it is intended to be set by the project. See also -:variable:`CMAKE_SYSTEM_INCLUDE_PATH` and :variable:`CMAKE_PREFIX_PATH`. +is empty, it is intended to be set by the project. + + +There is also an environment variable :envvar:`CMAKE_INCLUDE_PATH`, which is used +as an additional list of search directories. + +See also :variable:`CMAKE_SYSTEM_INCLUDE_PATH` and :variable:`CMAKE_PREFIX_PATH`. diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index 3b27fc3a6d..5eb86c603e 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -9,7 +9,7 @@ include: =============================== =============================================== Value Name =============================== =============================================== -``Absoft`` `Absoft Fortran`_ +``Absoft`` Absoft Fortran ``ADSP`` Analog VisualDSP++ ``AppleClang`` Apple Clang ``ARMCC`` ARM Compiler @@ -50,7 +50,6 @@ Value Name This variable is not guaranteed to be defined for all compilers or languages. -.. _Absoft Fortran: https://www.absoft.com .. _LLVM Clang: https://clang.llvm.org .. _Embarcadero: https://www.embarcadero.com .. _Classic Flang Fortran Compiler: https://github.com/flang-compiler/flang diff --git a/Help/variable/CMAKE_LIBRARY_PATH.rst b/Help/variable/CMAKE_LIBRARY_PATH.rst index 8135b65818..4265982c2c 100644 --- a/Help/variable/CMAKE_LIBRARY_PATH.rst +++ b/Help/variable/CMAKE_LIBRARY_PATH.rst @@ -3,5 +3,9 @@ CMAKE_LIBRARY_PATH :ref:`Semicolon-separated list <CMake Language Lists>` of directories specifying a search path for the :command:`find_library` command. By default it is empty, it is -intended to be set by the project. See also -:variable:`CMAKE_SYSTEM_LIBRARY_PATH` and :variable:`CMAKE_PREFIX_PATH`. +intended to be set by the project. + +There is also an environment variable :envvar:`CMAKE_LIBRARY_PATH`, which is used +as an additional list of search directories. + +See also :variable:`CMAKE_SYSTEM_LIBRARY_PATH` and :variable:`CMAKE_PREFIX_PATH`. diff --git a/Help/variable/CMAKE_LINK_DEPENDS_USE_LINKER.rst b/Help/variable/CMAKE_LINK_DEPENDS_USE_LINKER.rst new file mode 100644 index 0000000000..e1b37a59da --- /dev/null +++ b/Help/variable/CMAKE_LINK_DEPENDS_USE_LINKER.rst @@ -0,0 +1,12 @@ +CMAKE_LINK_DEPENDS_USE_LINKER +----------------------------- + +.. versionadded:: 3.27 + +For the :ref:`Makefile <Makefile Generators>` and +:ref:`Ninja <Ninja Generators>` generators, link dependencies are now, for a +selection of linkers, generated by the linker itself. By defining this +variable with value ``FALSE``, you can deactivate this feature. + +This feature is also deactivated if the :prop_tgt:`LINK_DEPENDS_NO_SHARED` +target property is true. diff --git a/Help/variable/CMAKE_PREFIX_PATH.rst b/Help/variable/CMAKE_PREFIX_PATH.rst index 1d4fd0b426..54f2aecde0 100644 --- a/Help/variable/CMAKE_PREFIX_PATH.rst +++ b/Help/variable/CMAKE_PREFIX_PATH.rst @@ -10,6 +10,9 @@ documentation. By default this is empty. It is intended to be set by the project. +There is also an environment variable :envvar:`CMAKE_PREFIX_PATH`, which is used +as an additional list of search prefixes. + See also :variable:`CMAKE_SYSTEM_PREFIX_PATH`, :variable:`CMAKE_INCLUDE_PATH`, :variable:`CMAKE_LIBRARY_PATH`, :variable:`CMAKE_PROGRAM_PATH`, and :variable:`CMAKE_IGNORE_PATH`. diff --git a/Help/variable/CMAKE_PROGRAM_PATH.rst b/Help/variable/CMAKE_PROGRAM_PATH.rst index 2d0c090df5..240bacb9a0 100644 --- a/Help/variable/CMAKE_PROGRAM_PATH.rst +++ b/Help/variable/CMAKE_PROGRAM_PATH.rst @@ -3,5 +3,9 @@ CMAKE_PROGRAM_PATH :ref:`Semicolon-separated list <CMake Language Lists>` of directories specifying a search path for the :command:`find_program` command. By default it is empty, it is -intended to be set by the project. See also -:variable:`CMAKE_SYSTEM_PROGRAM_PATH` and :variable:`CMAKE_PREFIX_PATH`. +intended to be set by the project. + +There is also an environment variable :envvar:`CMAKE_PROGRAM_PATH`, which is used +as an additional list of search directories. + +See also :variable:`CMAKE_SYSTEM_PROGRAM_PATH` and :variable:`CMAKE_PREFIX_PATH`. diff --git a/Help/variable/CMAKE_VS_DEBUGGER_COMMAND.rst b/Help/variable/CMAKE_VS_DEBUGGER_COMMAND.rst new file mode 100644 index 0000000000..b2c03a1d04 --- /dev/null +++ b/Help/variable/CMAKE_VS_DEBUGGER_COMMAND.rst @@ -0,0 +1,8 @@ +CMAKE_VS_DEBUGGER_COMMAND +------------------------- + +.. versionadded:: 3.27 + +This variable is used to initialize the :prop_tgt:`VS_DEBUGGER_COMMAND` +property on each target as it is created. See that target property +for additional information. diff --git a/Help/variable/CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS.rst b/Help/variable/CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS.rst new file mode 100644 index 0000000000..482aa67e8a --- /dev/null +++ b/Help/variable/CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS.rst @@ -0,0 +1,8 @@ +CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS +----------------------------------- + +.. versionadded:: 3.27 + +This variable is used to initialize the :prop_tgt:`VS_DEBUGGER_COMMAND_ARGUMENTS` +property on each target as it is created. See that target property +for additional information. diff --git a/Help/variable/CMAKE_VS_DEBUGGER_ENVIRONMENT.rst b/Help/variable/CMAKE_VS_DEBUGGER_ENVIRONMENT.rst new file mode 100644 index 0000000000..245ac5d7f3 --- /dev/null +++ b/Help/variable/CMAKE_VS_DEBUGGER_ENVIRONMENT.rst @@ -0,0 +1,8 @@ +CMAKE_VS_DEBUGGER_ENVIRONMENT +----------------------------- + +.. versionadded:: 3.27 + +This variable is used to initialize the :prop_tgt:`VS_DEBUGGER_ENVIRONMENT` +property on each target as it is created. See that target property +for additional information. diff --git a/Help/variable/CMAKE_VS_DEBUGGER_WORKING_DIRECTORY.rst b/Help/variable/CMAKE_VS_DEBUGGER_WORKING_DIRECTORY.rst new file mode 100644 index 0000000000..9100adbb43 --- /dev/null +++ b/Help/variable/CMAKE_VS_DEBUGGER_WORKING_DIRECTORY.rst @@ -0,0 +1,8 @@ +CMAKE_VS_DEBUGGER_WORKING_DIRECTORY +----------------------------------- + +.. versionadded:: 3.27 + +This variable is used to initialize the :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` +property on each target as it is created. See that target property +for additional information. diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in index e300782aee..8a1718bb48 100644 --- a/Modules/CMakeASMCompiler.cmake.in +++ b/Modules/CMakeASMCompiler.cmake.in @@ -17,5 +17,6 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ENV_VAR "@_CMAKE_ASM_COMPILER_ENV_VAR@") set(CMAKE_ASM@ASM_DIALECT@_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) set(CMAKE_ASM@ASM_DIALECT@_LINKER_PREFERENCE 0) +set(CMAKE_ASM@ASM_DIALECT@_LINKER_DEPFILE_SUPPORTED "@CMAKE_ASM_LINKER_DEPFILE_SUPPORTED@") @CMAKE_ASM_COMPILER_CUSTOM_CODE@ diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 8ae07a34e1..cf3a242a64 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -39,6 +39,7 @@ set(CMAKE_C_COMPILER_ID_RUN 1) set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) set(CMAKE_C_LINKER_PREFERENCE 10) +set(CMAKE_C_LINKER_DEPFILE_SUPPORTED "@CMAKE_C_LINKER_DEPFILE_SUPPORTED@") # Save compiler ABI information. set(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@") diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 57d595af30..3d7d55201b 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -30,6 +30,7 @@ set(CMAKE_CUDA_COMPILER_ID_RUN 1) set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu) set(CMAKE_CUDA_LINKER_PREFERENCE 15) set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED "@CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED@") set(CMAKE_CUDA_SIZEOF_DATA_PTR "@CMAKE_CUDA_SIZEOF_DATA_PTR@") set(CMAKE_CUDA_COMPILER_ABI "@CMAKE_CUDA_COMPILER_ABI@") diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 834c2e6b17..2052e7f903 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -50,6 +50,7 @@ endforeach() set(CMAKE_CXX_LINKER_PREFERENCE 30) set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_CXX_LINKER_DEPFILE_SUPPORTED "@CMAKE_CXX_LINKER_DEPFILE_SUPPORTED@") # Save compiler ABI information. set(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@") diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index c4ddf75e3f..9e38566755 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -165,13 +165,13 @@ endif () if (NOT _CMAKE_TOOLCHAIN_PREFIX) - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC|LCC") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|QCC|LCC") get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME) if (COMPILER_BASENAME MATCHES "^(.+-)?(clang\\+\\+|[gc]\\+\\+|clang-cl)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$") set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) set(_CMAKE_TOOLCHAIN_SUFFIX ${CMAKE_MATCH_3}) set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5}) - elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_COMPILER_TARGET) set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_CXX_COMPILER_TARGET}-) endif() @@ -186,7 +186,7 @@ if (NOT _CMAKE_TOOLCHAIN_PREFIX) if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$") set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) endif () - elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "TI") + elseif(CMAKE_CXX_COMPILER_ID MATCHES "TI") # TI compilers are named e.g. cl6x, cl470 or armcl.exe get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME) if (COMPILER_BASENAME MATCHES "^(.+)?cl([^.]+)?(\\.exe)?$") diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 67044fb3b2..403766e561 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -345,6 +345,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} set(id_platform ${CMAKE_VS_PLATFORM_NAME}) set(id_lang "${lang}") set(id_PostBuildEvent_Command "") + set(id_api_level "") if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^[Ll][Ll][Vv][Mm](_v[0-9]+(_xp)?)?$") set(id_cl_var "ClangClExecutable") elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^[Cc][Ll][Aa][Nn][Gg]([Cc][Ll]$|_[0-9])") @@ -430,9 +431,10 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} set(id_system "") endif() if(id_keyword STREQUAL "Android") + set(id_api_level "<AndroidAPILevel>android-${CMAKE_SYSTEM_VERSION}</AndroidAPILevel>") if(CMAKE_GENERATOR MATCHES "Visual Studio 14") set(id_system_version "<ApplicationTypeRevision>2.0</ApplicationTypeRevision>") - elseif(CMAKE_GENERATOR MATCHES "Visual Studio 1[56]") + elseif(CMAKE_GENERATOR MATCHES "Visual Studio 1[567]") set(id_system_version "<ApplicationTypeRevision>3.0</ApplicationTypeRevision>") else() set(id_system_version "") diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index fc81d0e5f6..a7caf2be8a 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -29,6 +29,7 @@ set(CMAKE_Fortran_COMPILER_ID_RUN 1) set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95;f03;F03;f08;F08@CMAKE_Fortran_VENDOR_SOURCE_FILE_EXTENSIONS@) set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) set(CMAKE_Fortran_LINKER_PREFERENCE 20) +set(CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED "@CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED@") if(UNIX) set(CMAKE_Fortran_OUTPUT_EXTENSION .o) else() diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in index 8a747c67d8..32c122366e 100644 --- a/Modules/CMakeHIPCompiler.cmake.in +++ b/Modules/CMakeHIPCompiler.cmake.in @@ -26,6 +26,7 @@ set(CMAKE_HIP_COMPILER_ID_RUN 1) set(CMAKE_HIP_SOURCE_FILE_EXTENSIONS hip) set(CMAKE_HIP_LINKER_PREFERENCE 90) set(CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_HIP_LINKER_DEPFILE_SUPPORTED "@CMAKE_HIP_LINKER_DEPFILE_SUPPORTED@") set(CMAKE_HIP_SIZEOF_DATA_PTR "@CMAKE_HIP_SIZEOF_DATA_PTR@") set(CMAKE_HIP_COMPILER_ABI "@CMAKE_HIP_COMPILER_ABI@") diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in index ea11a7aa36..0ceb80468c 100644 --- a/Modules/CMakeOBJCCompiler.cmake.in +++ b/Modules/CMakeOBJCCompiler.cmake.in @@ -37,6 +37,7 @@ set(CMAKE_OBJC_COMPILER_ID_RUN 1) set(CMAKE_OBJC_SOURCE_FILE_EXTENSIONS m) set(CMAKE_OBJC_IGNORE_EXTENSIONS h;H;o;O) set(CMAKE_OBJC_LINKER_PREFERENCE 5) +set(CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED "@CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED@") foreach (lang C CXX OBJCXX) foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS) diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in index 5d0b381257..f087ec3f52 100644 --- a/Modules/CMakeOBJCXXCompiler.cmake.in +++ b/Modules/CMakeOBJCXXCompiler.cmake.in @@ -54,6 +54,7 @@ endforeach() set(CMAKE_OBJCXX_LINKER_PREFERENCE 25) set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED "@CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED@") # Save compiler ABI information. set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@") diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index f9cf33fa9a..ff1cb7e6fd 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -262,8 +262,8 @@ installers. The most commonly-used variables are: Lists each of the executables and associated text label to be used to create Start Menu shortcuts. For example, setting this to the list ``ccmake;CMake`` will create a shortcut named "CMake" that will execute the - installed executable :program:`ccmake`. Not all CPack generators use it (at least - NSIS, and WIX do). + installed executable :program:`ccmake`. Not all CPack generators use it (at least + NSIS, Inno Setup and WIX do). .. variable:: CPACK_STRIP_FILES @@ -738,14 +738,16 @@ if(NOT CPACK_GENERATOR) ) endif() else() - option(CPACK_BINARY_7Z "Enable to build 7-Zip packages" OFF) - option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON) - option(CPACK_BINARY_NUGET "Enable to build NuGet packages" OFF) - option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF) - option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF) + option(CPACK_BINARY_7Z "Enable to build 7-Zip packages" OFF) + option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON) + option(CPACK_BINARY_INNOSETUP "Enable to build Inno Setup packages" OFF) + option(CPACK_BINARY_NUGET "Enable to build NuGet packages" OFF) + option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF) + option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF) mark_as_advanced( CPACK_BINARY_7Z CPACK_BINARY_NSIS + CPACK_BINARY_INNOSETUP CPACK_BINARY_NUGET CPACK_BINARY_WIX CPACK_BINARY_ZIP @@ -762,6 +764,7 @@ if(NOT CPACK_GENERATOR) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_FREEBSD FREEBSD) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_IFW IFW) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NSIS NSIS) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_INNOSETUP INNOSETUP) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NUGET NuGet) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PRODUCTBUILD productbuild) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_RPM RPM) @@ -869,6 +872,13 @@ if(NOT DEFINED CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE unset(_CPack_CMP0133) endif() +# Inno Setup specific variables +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + _cpack_set_default(CPACK_INNOSETUP_ARCHITECTURE "x86") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + _cpack_set_default(CPACK_INNOSETUP_ARCHITECTURE "x64") +endif() + # WiX specific variables _cpack_set_default(CPACK_WIX_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P}") diff --git a/Modules/Compiler/Clang-HIP.cmake b/Modules/Compiler/Clang-HIP.cmake index 4dbe2e8c01..7e3c99c905 100644 --- a/Modules/Compiler/Clang-HIP.cmake +++ b/Modules/Compiler/Clang-HIP.cmake @@ -1,4 +1,13 @@ include(Compiler/Clang) + +# +# For now, deactivate globally linker dependency file support because +# HIP compiler is based on Clang which provides support of other languages +# +foreach (lang IN ITEMS "C" "CXX" "OBJC" "OBJCXX" "Fortran" "ASM") + set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE) +endforeach() + __compiler_clang(HIP) __compiler_clang_cxx_standards(HIP) diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index 5930e377cb..f14020876f 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -52,6 +52,44 @@ macro(__compiler_gnu lang) set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") endif() + # define flags for linker depfile generation + if (NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED) + ## Ensure ninja tool is recent enough... + if(CMAKE_GENERATOR MATCHES "^Ninja") + # Ninja 1.10 or upper is required + execute_process(COMMAND "${CMAKE_MAKE_PROGRAM}" --version + OUTPUT_VARIABLE _ninja_version + ERROR_VARIABLE _ninja_version) + if (_ninja_version MATCHES "[0-9]+(\\.[0-9]+)*") + set (_ninja_version "${CMAKE_MATCH_0}") + endif() + if (_ninja_version VERSION_LESS "1.10") + set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE) + endif() + unset(_ninja_version) + endif() + + if (NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED) + ## check if this feature is supported by the linker + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE _linker_capabilities + ERROR_VARIABLE _linker_capabilities) + if(_linker_capabilities MATCHES "--dependency-file") + set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED TRUE) + else() + set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE) + endif() + unset(_linker_capabilities) + endif() + endif() + if (CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED) + set(CMAKE_${lang}_LINKER_DEPFILE_FLAGS "LINKER:--dependency-file,<DEP_FILE>") + set(CMAKE_${lang}_LINKER_DEPFILE_FORMAT gcc) + set(CMAKE_${lang}_LINK_DEPENDS_USE_LINKER TRUE) + else() + unset(CMAKE_${lang}_LINK_DEPENDS_USE_LINKER) + endif() + # Initial configuration flags. string(APPEND CMAKE_${lang}_FLAGS_INIT " ") string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g") diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index 0aca2838a7..32a7b3f5af 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -1,6 +1,6 @@ # This file is processed when the IAR C/C++ Compiler is used # -# CPU <arch> supported in CMake: 8051, Arm, AVR, MSP430, RH850, RISC-V, RL78, RX and V850 +# CPU <arch> supported in CMake: 8051, Arm, AVR, MSP430, RH850, RISC-V, RL78, RX, STM8 and V850 # # The compiler user documentation is architecture-dependent # and it can found with the product installation under <arch>/doc/{EW,BX}<arch>_DevelopmentGuide.ENU.pdf @@ -35,7 +35,9 @@ macro(__compiler_iar_ilink lang) __compiler_iar_common(${lang}) - set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " --silent") + set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> <TARGET> --replace <LINK_FLAGS> <OBJECTS>") @@ -46,7 +48,9 @@ macro(__compiler_iar_xlink lang) __compiler_iar_common(${lang}) - set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -S") + set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_APPEND "") diff --git a/Modules/Compiler/NVHPC-Fortran.cmake b/Modules/Compiler/NVHPC-Fortran.cmake index 5c0645737d..59755b3a71 100644 --- a/Modules/Compiler/NVHPC-Fortran.cmake +++ b/Modules/Compiler/NVHPC-Fortran.cmake @@ -1,4 +1,3 @@ include(Compiler/PGI-Fortran) include(Compiler/NVHPC) __compiler_nvhpc(Fortran) -set(CMAKE_Fortran_PREPROCESS_SOURCE_EXCLUDE_FLAGS_REGEX "(^| )-Werror +[a-z][a-z-]+( |$)") diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake index 474ac80efe..0593456ce7 100644 --- a/Modules/Compiler/NVHPC.cmake +++ b/Modules/Compiler/NVHPC.cmake @@ -13,5 +13,5 @@ include(Compiler/PGI) macro(__compiler_nvhpc lang) # Logic specific to NVHPC. set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") - set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror" "all-warnings") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") endmacro() diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index 3598fc7e20..fa324d8214 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -26,6 +26,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'" Label="Configuration"> <ConfigurationType>@id_config_type@</ConfigurationType> @id_toolset@ + @id_api_level@ <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> @@ -44,7 +45,7 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions> <MinimalRebuild>false</MinimalRebuild> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary Condition="'$(ApplicationType)'!='Android'">MultiThreadedDebugDLL</RuntimeLibrary> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>TurnOffAllWarnings</WarningLevel> diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 9a6cbd6bc4..e2cc497a65 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -278,6 +278,13 @@ External Project Definition URL of the git repository. Any URL understood by the ``git`` command may be used. + .. versionchanged:: 3.27 + A relative URL will be resolved based on the parent project's + remote, subject to :policy:`CMP0150`. See the policy documentation + for how the remote is selected, including conditions where the + remote selection can fail. Local filesystem remotes should + always use absolute paths. + ``GIT_TAG <tag>`` Git branch name, tag or commit hash. Note that branch names and tags should generally be specified as remote names (i.e. ``origin/myBranch`` @@ -1188,6 +1195,8 @@ The custom step could then be triggered from the main build like so:: #]=======================================================================] +include(${CMAKE_CURRENT_LIST_DIR}/ExternalProject/shared_internal_commands.cmake) + cmake_policy(PUSH) cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST @@ -4159,6 +4168,17 @@ function(ExternalProject_Add name) set_property(TARGET ${name} PROPERTY EXCLUDE_FROM_ALL TRUE) endif() + get_property(repo TARGET ${name} PROPERTY _EP_GIT_REPOSITORY) + if(NOT repo STREQUAL "") + cmake_policy(GET CMP0150 cmp0150 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR) + get_filename_component(work_dir "${source_dir}" PATH) + _ep_resolve_git_remote(resolved_git_repository "${repo}" "${cmp0150}" "${work_dir}") + set_property(TARGET ${name} PROPERTY _EP_GIT_REPOSITORY ${resolved_git_repository}) + endif() + # The 'complete' step depends on all other steps and creates a # 'done' mark. A dependent external project's 'configure' step # depends on the 'done' mark so that it rebuilds when this project diff --git a/Modules/ExternalProject/shared_internal_commands.cmake b/Modules/ExternalProject/shared_internal_commands.cmake new file mode 100644 index 0000000000..ca3cd9fec7 --- /dev/null +++ b/Modules/ExternalProject/shared_internal_commands.cmake @@ -0,0 +1,182 @@ +cmake_policy(VERSION 3.25) + +# Determine the remote URL of the project containing the working_directory. +# This will leave output_variable unset if the URL can't be determined. +function(_ep_get_git_remote_url output_variable working_directory) + set("${output_variable}" "" PARENT_SCOPE) + + find_package(Git QUIET REQUIRED) + + execute_process( + COMMAND ${GIT_EXECUTABLE} symbolic-ref --short HEAD + WORKING_DIRECTORY "${working_directory}" + OUTPUT_VARIABLE git_symbolic_ref + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + if(NOT git_symbolic_ref STREQUAL "") + # We are potentially on a branch. See if that branch is associated with + # an upstream remote (might be just a local one or not a branch at all). + execute_process( + COMMAND ${GIT_EXECUTABLE} config branch.${git_symbolic_ref}.remote + WORKING_DIRECTORY "${working_directory}" + OUTPUT_VARIABLE git_remote_name + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + endif() + + if(NOT git_remote_name) + # Can't select a remote based on a branch. If there's only one remote, + # or we have multiple remotes but one is called "origin", choose that. + execute_process( + COMMAND ${GIT_EXECUTABLE} remote + WORKING_DIRECTORY "${working_directory}" + OUTPUT_VARIABLE git_remote_list + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + string(REPLACE "\n" ";" git_remote_list "${git_remote_list}") + list(LENGTH git_remote_list git_remote_list_length) + + if(git_remote_list_length EQUAL 0) + message(FATAL_ERROR "Git remote not found in parent project.") + elseif(git_remote_list_length EQUAL 1) + list(GET git_remote_list 0 git_remote_name) + else() + set(base_warning_msg "Multiple git remotes found for parent project") + if("origin" IN_LIST git_remote_list) + message(WARNING "${base_warning_msg}, defaulting to origin.") + set(git_remote_name "origin") + else() + message(FATAL_ERROR "${base_warning_msg}, none of which are origin.") + endif() + endif() + endif() + + if(GIT_VERSION VERSION_LESS 1.7.5) + set(_git_remote_url_cmd_args config remote.${git_remote_name}.url) + elseif(GIT_VERSION VERSION_LESS 2.7) + set(_git_remote_url_cmd_args ls-remote --get-url ${git_remote_name}) + else() + set(_git_remote_url_cmd_args remote get-url ${git_remote_name}) + endif() + + execute_process( + COMMAND ${GIT_EXECUTABLE} ${_git_remote_url_cmd_args} + WORKING_DIRECTORY "${working_directory}" + OUTPUT_VARIABLE git_remote_url + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL LAST + ENCODING UTF-8 # Needed to handle non-ascii characters in local paths + ) + + set("${output_variable}" "${git_remote_url}" PARENT_SCOPE) +endfunction() + +function(_ep_is_relative_git_remote output_variable remote_url) + if(remote_url MATCHES "^\\.\\./") + set("${output_variable}" TRUE PARENT_SCOPE) + else() + set("${output_variable}" FALSE PARENT_SCOPE) + endif() +endfunction() + +# Return an absolute remote URL given an existing remote URL and relative path. +# The output_variable will be set to an empty string if an absolute URL +# could not be computed (no error message is output). +function(_ep_resolve_relative_git_remote + output_variable + parent_remote_url + relative_remote_url +) + set("${output_variable}" "" PARENT_SCOPE) + + if(parent_remote_url STREQUAL "") + return() + endif() + + string(REGEX MATCH + "^(([A-Za-z0-9][A-Za-z0-9+.-]*)://)?(([^/@]+)@)?(\\[[A-Za-z0-9:]+\\]|[^/:]+)?([/:]/?)(.+(\\.git)?/?)$" + git_remote_url_components + "${parent_remote_url}" + ) + + set(protocol "${CMAKE_MATCH_1}") + set(auth "${CMAKE_MATCH_3}") + set(host "${CMAKE_MATCH_5}") + set(separator "${CMAKE_MATCH_6}") + set(path "${CMAKE_MATCH_7}") + + string(REPLACE "/" ";" remote_path_components "${path}") + string(REPLACE "/" ";" relative_path_components "${relative_remote_url}") + + foreach(relative_path_component IN LISTS relative_path_components) + if(NOT relative_path_component STREQUAL "..") + break() + endif() + + list(LENGTH remote_path_components remote_path_component_count) + + if(remote_path_component_count LESS 1) + return() + endif() + + list(POP_BACK remote_path_components) + list(POP_FRONT relative_path_components) + endforeach() + + list(APPEND final_path_components ${remote_path_components} ${relative_path_components}) + list(JOIN final_path_components "/" path) + + set("${output_variable}" "${protocol}${auth}${host}${separator}${path}" PARENT_SCOPE) +endfunction() + +# The output_variable will be set to the original git_repository if it +# could not be resolved (no error message is output). The original value is +# also returned if it doesn't need to be resolved. +function(_ep_resolve_git_remote + output_variable + git_repository + cmp0150 + cmp0150_old_base_dir +) + if(git_repository STREQUAL "") + set("${output_variable}" "" PARENT_SCOPE) + return() + endif() + + _ep_is_relative_git_remote(_git_repository_is_relative "${git_repository}") + + if(NOT _git_repository_is_relative) + set("${output_variable}" "${git_repository}" PARENT_SCOPE) + return() + endif() + + if(cmp0150 STREQUAL "NEW") + _ep_get_git_remote_url(_parent_git_remote_url "${CMAKE_CURRENT_SOURCE_DIR}") + _ep_resolve_relative_git_remote(_resolved_git_remote_url "${_parent_git_remote_url}" "${git_repository}") + + if(_resolved_git_remote_url STREQUAL "") + message(FATAL_ERROR + "Failed to resolve relative git remote URL:\n" + " Relative URL: ${git_repository}\n" + " Parent URL: ${_parent_git_remote_url}" + ) + endif() + set("${output_variable}" "${_resolved_git_remote_url}" PARENT_SCOPE) + return() + elseif(cmp0150 STREQUAL "") + cmake_policy(GET_WARNING CMP0150 _cmp0150_warning) + message(AUTHOR_WARNING + "${_cmp0150_warning}\n" + "A relative GIT_REPOSITORY path was detected. " + "This will be interpreted as a local path to where the project is being cloned. " + "Set GIT_REPOSITORY to an absolute path or set policy CMP0150 to NEW to avoid " + "this warning." + ) + endif() + + set("${output_variable}" "${cmp0150_old_base_dir}/${git_repository}" PARENT_SCOPE) +endfunction() diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index dd5f617acd..74ac8aab2a 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -1076,6 +1076,8 @@ current working directory. #]=======================================================================] +include(${CMAKE_CURRENT_LIST_DIR}/ExternalProject/shared_internal_commands.cmake) + #======================================================================= # Recording and retrieving content details for later population #======================================================================= @@ -1223,6 +1225,7 @@ function(FetchContent_Declare contentName) # cannot check for multi-value arguments with this method. We will have to # handle the URL keyword differently. set(oneValueArgs + GIT_REPOSITORY SVN_REPOSITORY DOWNLOAD_NO_EXTRACT DOWNLOAD_EXTRACT_TIMESTAMP @@ -1242,6 +1245,30 @@ function(FetchContent_Declare contentName) set(ARG_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") endif() + if(ARG_GIT_REPOSITORY) + # We resolve the GIT_REPOSITORY here so that we get the right parent in the + # remote selection logic. In the sub-build, ExternalProject_Add() would see + # the private sub-build directory as the parent project, but the parent + # project should be the one that called FetchContent_Declare(). We resolve + # a relative repo here so that the sub-build's ExternalProject_Add() only + # ever sees a non-relative repo. + # Since these checks may be non-trivial on some platforms (notably Windows), + # don't perform them if we won't be using these details. This also allows + # projects to override calls with relative URLs when they have checked out + # the parent project in an unexpected way, such as from a mirror or fork. + set(savedDetailsPropertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${savedDetailsPropertyName} DEFINED) + if(NOT alreadyDefined) + cmake_policy(GET CMP0150 cmp0150 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + _ep_resolve_git_remote(_resolved_git_repository + "${ARG_GIT_REPOSITORY}" "${cmp0150}" "${FETCHCONTENT_BASE_DIR}" + ) + set(ARG_GIT_REPOSITORY "${_resolved_git_repository}") + endif() + endif() + if(ARG_SVN_REPOSITORY) # Add a hash of the svn repository URL to the source dir. This works # around the problem where if the URL changes, the download would diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 19bef9471c..39a1163533 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -93,6 +93,11 @@ BLAS/LAPACK Vendors ``ACML``, ``ACML_MP``, ``ACML_GPU`` AMD Core Math Library +``AOCL``, ``AOCL_mt`` + .. versionadded:: 3.27 + + AMD Optimizing CPU Libraries + ``Apple``, ``NAS`` Apple BLAS (Accelerate), and Apple NAS (vecLib) @@ -848,6 +853,38 @@ if(BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All") unset(_blas_flame_lib) endif() +# AOCL's blis library? (https://developer.amd.com/amd-aocl/) +if(BLA_VENDOR MATCHES "AOCL" OR BLA_VENDOR STREQUAL "All") + set(_blas_aocl_lib "blis") + + if(_blas_sizeof_integer EQUAL 8) + set(_blas_aocl_subdir "ILP64") + else() + set(_blas_aocl_subdir "LP64") + endif() + + # Check for multi-threaded support + if(BLA_VENDOR MATCHES "_mt") + string(APPEND _blas_aocl_lib "-mt") + endif() + + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "${_blas_aocl_lib}" + "" + "" + "${_blas_aocl_subdir}" + ) + endif() + + unset(_blas_aocl_lib) + unset(_blas_aocl_subdir) +endif() + # BLAS in the ATLAS library? (http://math-atlas.sourceforge.net/) if(BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 4423ebb628..107ced7f83 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -29,8 +29,8 @@ The CUDA Toolkit search behavior uses the following order: precedence. The directory specified here must be such that the executable ``nvcc`` or - the appropriate ``version.txt`` file can be found underneath the specified - directory. + the appropriate ``version.txt`` or ``version.json`` file can be found + underneath the specified directory. 3. If the CUDA_PATH environment variable is defined, it will be searched for ``nvcc``. @@ -388,7 +388,6 @@ nvRTC """"" The `nvRTC <https://docs.nvidia.com/cuda/nvrtc/index.html>`_ (Runtime Compilation) library. -This is a shared library only. Targets Created: @@ -492,7 +491,7 @@ Result variables ``CUDAToolkit_VERSION`` The exact version of the CUDA Toolkit found (as reported by - ``nvcc --version`` or ``version.txt``). + ``nvcc --version``, ``version.txt``, or ``version.json``). ``CUDAToolkit_VERSION_MAJOR`` The major version of the CUDA Toolkit. @@ -519,7 +518,7 @@ Result variables .. versionadded:: 3.18 The path to the CUDA Toolkit directory containing the nvvm directory and - version.txt. + either version.txt or version.json. ``CUDAToolkit_TARGET_DIR`` The path to the CUDA Toolkit directory including the target architecture @@ -604,7 +603,7 @@ else() if(NOT CUDAToolkit_NVCC_EXECUTABLE) find_file(CUDAToolkit_SENTINEL_FILE - NAMES version.txt + NAMES version.txt version.json PATHS ${arg_SEARCH_PATHS} NO_DEFAULT_PATH ) @@ -645,14 +644,43 @@ else() function(_CUDAToolkit_find_version_file result_variable) # We first check for a non-scattered installation to prefer it over a scattered installation. - if(CUDAToolkit_ROOT AND EXISTS "${CUDAToolkit_ROOT}/version.txt") - set(${result_variable} "${CUDAToolkit_ROOT}/version.txt" PARENT_SCOPE) - elseif(CUDAToolkit_ROOT_DIR AND EXISTS "${CUDAToolkit_ROOT_DIR}/version.txt") - set(${result_variable} "${CUDAToolkit_ROOT_DIR}/version.txt" PARENT_SCOPE) - elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt") - set(${result_variable} "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt" PARENT_SCOPE) - elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt") - set(${result_variable} "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt" PARENT_SCOPE) + set(version_files version.txt version.json) + foreach(vf IN LISTS version_files) + if(CUDAToolkit_ROOT AND EXISTS "${CUDAToolkit_ROOT}/${vf}") + set(${result_variable} "${CUDAToolkit_ROOT}/${vf}" PARENT_SCOPE) + break() + elseif(CUDAToolkit_ROOT_DIR AND EXISTS "${CUDAToolkit_ROOT_DIR}/${vf}") + set(${result_variable} "${CUDAToolkit_ROOT_DIR}/${vf}" PARENT_SCOPE) + break() + elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/${vf}") + set(${result_variable} "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/${vf}" PARENT_SCOPE) + break() + elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/${vf}") + set(${result_variable} "${CMAKE_SYSROOT}/usr/lib/cuda/${vf}" PARENT_SCOPE) + break() + endif() + endforeach() + endfunction() + + function(_CUDAToolkit_parse_version_file version_file) + if(version_file) + file(READ "${version_file}" file_conents) + cmake_path(GET version_file EXTENSION LAST_ONLY version_ext) + if(version_ext STREQUAL ".json") + string(JSON cuda_version_info GET "${file_conents}" "cuda" "version") + set(cuda_version_match_regex [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + elseif(version_ext STREQUAL ".txt") + set(cuda_version_info "${file_conents}") + set(cuda_version_match_regex [=[CUDA Version ([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + endif() + + if(cuda_version_info MATCHES "${cuda_version_match_regex}") + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}" PARENT_SCOPE) + set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}" PARENT_SCOPE) + message(STATUS "_CUDAToolkit_parse_version_file") + endif() endif() endfunction() @@ -799,15 +827,7 @@ else() unset(NVCC_OUT) else() _CUDAToolkit_find_version_file(version_file) - if(version_file) - file(READ "${version_file}" VERSION_INFO) - if(VERSION_INFO MATCHES [=[CUDA Version ([0-9]+)\.([0-9]+)\.([0-9]+)]=]) - set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") - set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") - set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") - set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") - endif() - endif() + _CUDAToolkit_parse_version_file("${version_file}") endif() endif() @@ -945,6 +965,19 @@ if(CUDAToolkit_FOUND) file(REAL_PATH "${CUDAToolkit_LIBRARY_DIR}/../" _cmake_search_dir) list(APPEND CUDAToolkit_LIBRARY_SEARCH_DIRS "${_cmake_search_dir}") endif() + + # If no `CUDAToolkit_LIBRARY_ROOT` exists set it based on CUDAToolkit_LIBRARY_DIR + if(NOT DEFINED CUDAToolkit_LIBRARY_ROOT) + foreach(CUDAToolkit_search_loc IN LISTS CUDAToolkit_LIBRARY_DIR CUDAToolkit_BIN_DIR) + get_filename_component(CUDAToolkit_possible_lib_root "${CUDAToolkit_search_loc}" DIRECTORY ABSOLUTE) + if(EXISTS "${CUDAToolkit_possible_lib_root}/nvvm/") + set(CUDAToolkit_LIBRARY_ROOT "${CUDAToolkit_possible_lib_root}") + break() + endif() + endforeach() + unset(CUDAToolkit_search_loc) + unset(CUDAToolkit_possible_lib_root) + endif() endif() @@ -1042,7 +1075,11 @@ if(CUDAToolkit_FOUND) endif() _CUDAToolkit_find_and_add_import_lib(culibos) # it's a static library - foreach (cuda_lib cublasLt cufft curand nppc nvjpeg) + foreach (cuda_lib cublasLt cufft nvjpeg) + _CUDAToolkit_find_and_add_import_lib(${cuda_lib}) + _CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS cudart_static_deps culibos) + endforeach() + foreach (cuda_lib curand nppc) _CUDAToolkit_find_and_add_import_lib(${cuda_lib}) _CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS culibos) endforeach() @@ -1146,7 +1183,12 @@ if(CUDAToolkit_FOUND) _CUDAToolkit_find_and_add_import_lib(nvrtc DEPS nvrtc_builtins nvJitLink) if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.5.0) _CUDAToolkit_find_and_add_import_lib(nvrtc_builtins_static ALT nvrtc-builtins_static DEPS cuda_driver) - _CUDAToolkit_find_and_add_import_lib(nvrtc_static DEPS nvrtc_builtins_static nvptxcompiler_static nvJitLink_static) + if(NOT TARGET CUDA::nvrtc_static) + _CUDAToolkit_find_and_add_import_lib(nvrtc_static DEPS nvrtc_builtins_static nvptxcompiler_static nvJitLink_static) + if(TARGET CUDA::nvrtc_static AND WIN32 AND NOT (BORLAND OR MINGW OR CYGWIN)) + target_link_libraries(CUDA::nvrtc_static INTERFACE Ws2_32.lib) + endif() + endif() endif() _CUDAToolkit_find_and_add_import_lib(nvml ALT nvidia-ml nvml) diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake index ef9801eb24..76f47590c3 100644 --- a/Modules/FindDoxygen.cmake +++ b/Modules/FindDoxygen.cmake @@ -76,7 +76,8 @@ Functions [ALL] [USE_STAMP_FILE] [WORKING_DIRECTORY dir] - [COMMENT comment]) + [COMMENT comment] + [CONFIG_FILE filename]) The function constructs a ``Doxyfile`` and defines a custom target that runs Doxygen on that generated file. The listed files and directories are used as @@ -97,6 +98,10 @@ Functions the :command:`add_custom_target` command used to create the custom target internally. + .. versionadded:: 3.27 + If ``CONFIG_FILE`` is set, the given file provided with full-path + will be used as doxygen configuration file + .. versionadded:: 3.12 If ``ALL`` is set, the target will be added to the default build target. @@ -864,7 +869,7 @@ endfunction() function(doxygen_add_docs targetName) set(_options ALL USE_STAMP_FILE) - set(_one_value_args WORKING_DIRECTORY COMMENT) + set(_one_value_args WORKING_DIRECTORY COMMENT CONFIG_FILE) set(_multi_value_args) cmake_parse_arguments(_args "${_options}" @@ -1166,8 +1171,15 @@ doxygen_add_docs() for target ${targetName}") # Prepare doxygen configuration file set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in") - set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.${targetName}") - configure_file("${_doxyfile_template}" "${_target_doxyfile}") + if(_args_CONFIG_FILE) + if(NOT EXISTS "${_args_CONFIG_FILE}") + message(FATAL_ERROR "Option CONFIG_FILE specifies file:\n ${_args_CONFIG_FILE}\nbut it does not exist.") + endif() + set(_target_doxyfile "${_args_CONFIG_FILE}") + else() + set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.${targetName}") + configure_file("${_doxyfile_template}" "${_target_doxyfile}") + endif() unset(_all) if(${_args_ALL}) diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index 64163b008a..27f9b0e199 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -290,6 +290,13 @@ set(_JNI_JAVA_DIRECTORIES_BASE # Arch Linux specific paths for default JVM /usr/lib/jvm/default # Ubuntu specific paths for default JVM + /usr/lib/jvm/java-21-openjdk-{libarch} # Ubuntu 23.04 + /usr/lib/jvm/java-20-openjdk-{libarch} # Ubuntu 22.10 + /usr/lib/jvm/java-19-openjdk-{libarch} # Ubuntu 22.04 LTS + /usr/lib/jvm/java-18-openjdk-{libarch} # Ubuntu 22.04 LTS + /usr/lib/jvm/java-17-openjdk-{libarch} # Ubuntu 18.04 LTS + /usr/lib/jvm/java-16-openjdk-{libarch} # Ubuntu 20.04 LTS + /usr/lib/jvm/java-13-openjdk-{libarch} # Ubuntu 20.04 LTS /usr/lib/jvm/java-11-openjdk-{libarch} # Ubuntu 18.04 LTS /usr/lib/jvm/java-8-openjdk-{libarch} # Ubuntu 15.10 /usr/lib/jvm/java-7-openjdk-{libarch} # Ubuntu 15.10 diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 17117bd871..4d3ab5a0f3 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -561,6 +561,29 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) endif() endif() + # AOCL? (https://developer.amd.com/amd-aocl/) + if(NOT LAPACK_LIBRARIES + AND (BLA_VENDOR MATCHES "AOCL" OR BLA_VENDOR STREQUAL "All")) + if(_lapack_sizeof_integer EQUAL 8) + set(_lapack_aocl_subdir "ILP64") + else() + set(_lapack_aocl_subdir "LP64") + endif() + + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "flame" + "-fopenmp" + "" + "${_lapack_aocl_subdir}" + "${BLAS_LIBRARIES}" + ) + unset(_lapack_aocl_subdir) + endif() + # LAPACK in SCSL library? (SGI/Cray Scientific Library) if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All")) diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index 31ef1c7d53..e6f44e0cad 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -335,6 +335,8 @@ Hints constraints is founded. This is the default if policy :policy:`CMP0094` is set to ``NEW``. + See also ``Python_FIND_UNVERSIONED_NAMES``. + ``Python_FIND_REGISTRY`` .. versionadded:: 3.13 @@ -442,6 +444,8 @@ Hints This is the default. * ``NEVER``: The generic name are not searched at all. + See also ``Python_FIND_STRATEGY``. + Artifacts Specification ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake index 41d9b689ac..0575ea5a45 100644 --- a/Modules/FindPython2.cmake +++ b/Modules/FindPython2.cmake @@ -234,6 +234,8 @@ Hints constraints is founded. This is the default if policy :policy:`CMP0094` is set to ``NEW``. + See also ``Python2_FIND_UNVERSIONED_NAMES``. + ``Python2_FIND_REGISTRY`` .. versionadded:: 3.13 @@ -341,6 +343,8 @@ Hints This is the default. * ``NEVER``: The generic name are not searched at all. + See also ``Python2_FIND_STRATEGY``. + Artifacts Specification ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index ae086e8546..18929b2d92 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -333,6 +333,8 @@ Hints constraints is founded. This is the default if policy :policy:`CMP0094` is set to ``NEW``. + See also ``Python3_FIND_UNVERSIONED_NAMES``. + ``Python3_FIND_REGISTRY`` .. versionadded:: 3.13 @@ -440,6 +442,8 @@ Hints This is the default. * ``NEVER``: The generic name are not searched at all. + See also ``Python3_FIND_STRATEGY``. + Artifacts Specification ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake index 6f6483ab73..1047e4fb87 100644 --- a/Modules/FindX11.cmake +++ b/Modules/FindX11.cmake @@ -22,55 +22,77 @@ and also the following more fine grained variables and targets: :: - X11_ICE_INCLUDE_PATH, X11_ICE_LIB, X11_ICE_FOUND, X11::ICE - X11_SM_INCLUDE_PATH, X11_SM_LIB, X11_SM_FOUND, X11::SM - X11_X11_INCLUDE_PATH, X11_X11_LIB, X11::X11 + X11_ICE_INCLUDE_PATH, X11_ICE_LIB, X11_ICE_FOUND, X11::ICE + X11_SM_INCLUDE_PATH, X11_SM_LIB, X11_SM_FOUND, X11::SM + X11_X11_INCLUDE_PATH, X11_X11_LIB, X11::X11 X11_Xaccessrules_INCLUDE_PATH, - X11_Xaccessstr_INCLUDE_PATH, X11_Xaccess_FOUND - X11_Xau_INCLUDE_PATH, X11_Xau_LIB, X11_Xau_FOUND, X11::Xau - X11_xcb_INCLUDE_PATH, X11_xcb_LIB, X11_xcb_FOUND, X11::xcb - X11_X11_xcb_INCLUDE_PATH, X11_X11_xcb_LIB, X11_X11_xcb_FOUND, X11::X11_xcb - X11_xcb_cursor_INCLUDE_PATH, X11_xcb_cursor_LIB, X11_xcb_cursor_FOUND, X11::xcb_cursor - X11_xcb_icccm_INCLUDE_PATH, X11_xcb_icccm_LIB, X11_xcb_icccm_FOUND, X11::xcb_icccm - X11_xcb_randr_INCLUDE_PATH, X11_xcb_randr_LIB, X11_xcb_randr_FOUND, X11::xcb_randr - X11_xcb_shape_INCLUDE_PATH, X11_xcb_shape_LIB, X11_xcb_shape_FOUND, X11::xcb_shape - X11_xcb_util_INCLUDE_PATH, X11_xcb_util_LIB, X11_xcb_util_FOUND, X11::xcb_util - X11_xcb_xfixes_INCLUDE_PATH, X11_xcb_xfixes_LIB, X11_xcb_xfixes_FOUND, X11::xcb_xfixes - X11_xcb_xrm_INCLUDE_PATH, X11_xcb_xrm_LIB, X11_xcb_xrm_FOUND, X11::xcb_xrm - X11_xcb_xtest_INCLUDE_PATH, X11_xcb_xtest_LIB, X11_xcb_xtest_FOUND, X11::xcb_xtest - X11_xcb_keysyms_INCLUDE_PATH, X11_xcb_keysyms_LIB,X11_xcb_keysyms_FOUND,X11::xcb_keysyms - X11_xcb_xkb_INCLUDE_PATH, X11_xcb_xkb_LIB, X11_xcb_xkb_FOUND, X11::xcb_xkb - X11_Xcomposite_INCLUDE_PATH, X11_Xcomposite_LIB, X11_Xcomposite_FOUND, X11::Xcomposite - X11_Xcursor_INCLUDE_PATH, X11_Xcursor_LIB, X11_Xcursor_FOUND, X11::Xcursor - X11_Xdamage_INCLUDE_PATH, X11_Xdamage_LIB, X11_Xdamage_FOUND, X11::Xdamage - X11_Xdmcp_INCLUDE_PATH, X11_Xdmcp_LIB, X11_Xdmcp_FOUND, X11::Xdmcp - X11_Xext_INCLUDE_PATH, X11_Xext_LIB, X11_Xext_FOUND, X11::Xext - X11_Xxf86misc_INCLUDE_PATH, X11_Xxf86misc_LIB, X11_Xxf86misc_FOUND, X11::Xxf86misc - X11_Xxf86vm_INCLUDE_PATH, X11_Xxf86vm_LIB X11_Xxf86vm_FOUND, X11::Xxf86vm - X11_Xfixes_INCLUDE_PATH, X11_Xfixes_LIB, X11_Xfixes_FOUND, X11::Xfixes - X11_Xft_INCLUDE_PATH, X11_Xft_LIB, X11_Xft_FOUND, X11::Xft - X11_Xi_INCLUDE_PATH, X11_Xi_LIB, X11_Xi_FOUND, X11::Xi - X11_Xinerama_INCLUDE_PATH, X11_Xinerama_LIB, X11_Xinerama_FOUND, X11::Xinerama + X11_Xaccessstr_INCLUDE_PATH, X11_Xaccess_FOUND + X11_Xau_INCLUDE_PATH, X11_Xau_LIB, X11_Xau_FOUND, X11::Xau + X11_xcb_INCLUDE_PATH, X11_xcb_LIB, X11_xcb_FOUND, X11::xcb + X11_X11_xcb_INCLUDE_PATH, X11_X11_xcb_LIB, X11_X11_xcb_FOUND, X11::X11_xcb + X11_xcb_composite_INCLUDE_PATH, X11_xcb_composite_LIB, X11_xcb_composite_FOUND, X11::xcb_composite + X11_xcb_cursor_INCLUDE_PATH, X11_xcb_cursor_LIB, X11_xcb_cursor_FOUND, X11::xcb_cursor + X11_xcb_damage_INCLUDE_PATH, X11_xcb_damage_LIB, X11_xcb_damage_FOUND, X11::xcb_damage + X11_xcb_dpms_INCLUDE_PATH, X11_xcb_dpms_LIB, X11_xcb_dpms_FOUND, X11::xcb_dpms + X11_xcb_dri2_INCLUDE_PATH, X11_xcb_dri2_LIB, X11_xcb_dri2_FOUND, X11::xcb_dri2 + X11_xcb_dri3_INCLUDE_PATH, X11_xcb_dri3_LIB, X11_xcb_dri3_FOUND, X11::xcb_dri3 + X11_xcb_errors_INCLUDE_PATH, X11_xcb_errors_LIB, X11_xcb_errors_FOUND, X11::xcb_errors + X11_xcb_ewmh_INCLUDE_PATH, X11_xcb_ewmh_LIB, X11_xcb_ewmh_FOUND, X11::xcb_ewmh + X11_xcb_glx_INCLUDE_PATH, X11_xcb_glx_LIB, X11_xcb_glx_FOUND, X11::xcb_glx + X11_xcb_icccm_INCLUDE_PATH, X11_xcb_icccm_LIB, X11_xcb_icccm_FOUND, X11::xcb_icccm + X11_xcb_image_INCLUDE_PATH, X11_xcb_image_LIB, X11_xcb_image_FOUND, X11::xcb_image + X11_xcb_keysyms_INCLUDE_PATH, X11_xcb_keysyms_LIB, X11_xcb_keysyms_FOUND, X11::xcb_keysyms + X11_xcb_present_INCLUDE_PATH, X11_xcb_present_LIB, X11_xcb_present_FOUND, X11::xcb_present + X11_xcb_randr_INCLUDE_PATH, X11_xcb_randr_LIB, X11_xcb_randr_FOUND, X11::xcb_randr + X11_xcb_record_INCLUDE_PATH, X11_xcb_record_LIB, X11_xcb_record_FOUND, X11::xcb_record + X11_xcb_render_INCLUDE_PATH, X11_xcb_render_LIB, X11_xcb_render_FOUND, X11::xcb_render + X11_xcb_render_util_INCLUDE_PATH,X11_xcb_render_util_LIB,X11_xcb_render_util_FOUND,X11::xcb_render_util + X11_xcb_res_INCLUDE_PATH, X11_xcb_res_LIB, X11_xcb_res_FOUND, X11::xcb_res + X11_xcb_screensaver_INCLUDE_PATH,X11_xcb_screensaver_LIB,X11_xcb_screensaver_FOUND,X11::xcb_screensaver + X11_xcb_shape_INCLUDE_PATH, X11_xcb_shape_LIB, X11_xcb_shape_FOUND, X11::xcb_shape + X11_xcb_shm_INCLUDE_PATH, X11_xcb_shm_LIB, X11_xcb_shm_FOUND, X11::xcb_shm + X11_xcb_sync_INCLUDE_PATH, X11_xcb_sync_LIB, X11_xcb_sync_FOUND, X11::xcb_sync + X11_xcb_util_INCLUDE_PATH, X11_xcb_util_LIB, X11_xcb_util_FOUND, X11::xcb_util + X11_xcb_xf86dri_INCLUDE_PATH, X11_xcb_xf86dri_LIB, X11_xcb_xf86dri_FOUND, X11::xcb_xf86dri + X11_xcb_xfixes_INCLUDE_PATH, X11_xcb_xfixes_LIB, X11_xcb_xfixes_FOUND, X11::xcb_xfixes + X11_xcb_xinerama_INCLUDE_PATH, X11_xcb_xinerama_LIB, X11_xcb_xinerama_FOUND, X11::xcb_xinerama + X11_xcb_xinput_INCLUDE_PATH, X11_xcb_xinput_LIB, X11_xcb_xinput_FOUND, X11::xcb_xinput + X11_xcb_xkb_INCLUDE_PATH, X11_xcb_xkb_LIB, X11_xcb_xkb_FOUND, X11::xcb_xkb + X11_xcb_xrm_INCLUDE_PATH, X11_xcb_xrm_LIB, X11_xcb_xrm_FOUND, X11::xcb_xrm + X11_xcb_xtest_INCLUDE_PATH, X11_xcb_xtest_LIB, X11_xcb_xtest_FOUND, X11::xcb_xtest + X11_xcb_xvmc_INCLUDE_PATH, X11_xcb_xvmc_LIB, X11_xcb_xvmc_FOUND, X11::xcb_xvmc + X11_xcb_xv_INCLUDE_PATH, X11_xcb_xv_LIB, X11_xcb_xv_FOUND X11::xcb_xv + X11_Xcomposite_INCLUDE_PATH, X11_Xcomposite_LIB, X11_Xcomposite_FOUND, X11::Xcomposite + X11_Xcursor_INCLUDE_PATH, X11_Xcursor_LIB, X11_Xcursor_FOUND, X11::Xcursor + X11_Xdamage_INCLUDE_PATH, X11_Xdamage_LIB, X11_Xdamage_FOUND, X11::Xdamage + X11_Xdmcp_INCLUDE_PATH, X11_Xdmcp_LIB, X11_Xdmcp_FOUND, X11::Xdmcp + X11_Xext_INCLUDE_PATH, X11_Xext_LIB, X11_Xext_FOUND, X11::Xext + X11_Xxf86misc_INCLUDE_PATH, X11_Xxf86misc_LIB, X11_Xxf86misc_FOUND, X11::Xxf86misc + X11_Xxf86vm_INCLUDE_PATH, X11_Xxf86vm_LIB X11_Xxf86vm_FOUND, X11::Xxf86vm + X11_Xfixes_INCLUDE_PATH, X11_Xfixes_LIB, X11_Xfixes_FOUND, X11::Xfixes + X11_Xft_INCLUDE_PATH, X11_Xft_LIB, X11_Xft_FOUND, X11::Xft + X11_Xi_INCLUDE_PATH, X11_Xi_LIB, X11_Xi_FOUND, X11::Xi + X11_Xinerama_INCLUDE_PATH, X11_Xinerama_LIB, X11_Xinerama_FOUND, X11::Xinerama X11_Xkb_INCLUDE_PATH, - X11_Xkblib_INCLUDE_PATH, X11_Xkb_FOUND, X11::Xkb - X11_xkbcommon_INCLUDE_PATH, X11_xkbcommon_LIB, X11_xkbcommon_FOUND, X11::xkbcommon - X11_xkbcommon_X11_INCLUDE_PATH,X11_xkbcommon_X11_LIB,X11_xkbcommon_X11_FOUND,X11::xkbcommon_X11 - X11_xkbfile_INCLUDE_PATH, X11_xkbfile_LIB, X11_xkbfile_FOUND, X11::xkbfile - X11_Xmu_INCLUDE_PATH, X11_Xmu_LIB, X11_Xmu_FOUND, X11::Xmu - X11_Xpm_INCLUDE_PATH, X11_Xpm_LIB, X11_Xpm_FOUND, X11::Xpm - X11_Xtst_INCLUDE_PATH, X11_Xtst_LIB, X11_Xtst_FOUND, X11::Xtst - X11_Xrandr_INCLUDE_PATH, X11_Xrandr_LIB, X11_Xrandr_FOUND, X11::Xrandr - X11_Xrender_INCLUDE_PATH, X11_Xrender_LIB, X11_Xrender_FOUND, X11::Xrender - X11_XRes_INCLUDE_PATH, X11_XRes_LIB, X11_XRes_FOUND, X11::XRes - X11_Xss_INCLUDE_PATH, X11_Xss_LIB, X11_Xss_FOUND, X11::Xss - X11_Xt_INCLUDE_PATH, X11_Xt_LIB, X11_Xt_FOUND, X11::Xt - X11_Xutil_INCLUDE_PATH, X11_Xutil_FOUND, X11::Xutil - X11_Xv_INCLUDE_PATH, X11_Xv_LIB, X11_Xv_FOUND, X11::Xv - X11_dpms_INCLUDE_PATH, (in X11_Xext_LIB), X11_dpms_FOUND - X11_XShm_INCLUDE_PATH, (in X11_Xext_LIB), X11_XShm_FOUND - X11_Xshape_INCLUDE_PATH, (in X11_Xext_LIB), X11_Xshape_FOUND - X11_XSync_INCLUDE_PATH, (in X11_Xext_LIB), X11_XSync_FOUND - X11_Xaw_INCLUDE_PATH, X11_Xaw_LIB X11_Xaw_FOUND X11::Xaw + X11_Xkblib_INCLUDE_PATH, X11_Xkb_FOUND, X11::Xkb + X11_xkbcommon_INCLUDE_PATH, X11_xkbcommon_LIB, X11_xkbcommon_FOUND, X11::xkbcommon + X11_xkbcommon_X11_INCLUDE_PATH, X11_xkbcommon_X11_LIB, X11_xkbcommon_X11_FOUND, X11::xkbcommon_X11 + X11_xkbfile_INCLUDE_PATH, X11_xkbfile_LIB, X11_xkbfile_FOUND, X11::xkbfile + X11_Xmu_INCLUDE_PATH, X11_Xmu_LIB, X11_Xmu_FOUND, X11::Xmu + X11_Xpm_INCLUDE_PATH, X11_Xpm_LIB, X11_Xpm_FOUND, X11::Xpm + X11_Xtst_INCLUDE_PATH, X11_Xtst_LIB, X11_Xtst_FOUND, X11::Xtst + X11_Xrandr_INCLUDE_PATH, X11_Xrandr_LIB, X11_Xrandr_FOUND, X11::Xrandr + X11_Xrender_INCLUDE_PATH, X11_Xrender_LIB, X11_Xrender_FOUND, X11::Xrender + X11_XRes_INCLUDE_PATH, X11_XRes_LIB, X11_XRes_FOUND, X11::XRes + X11_Xss_INCLUDE_PATH, X11_Xss_LIB, X11_Xss_FOUND, X11::Xss + X11_Xt_INCLUDE_PATH, X11_Xt_LIB, X11_Xt_FOUND, X11::Xt + X11_Xutil_INCLUDE_PATH, X11_Xutil_FOUND, X11::Xutil + X11_Xv_INCLUDE_PATH, X11_Xv_LIB, X11_Xv_FOUND, X11::Xv + X11_dpms_INCLUDE_PATH, (in X11_Xext_LIB), X11_dpms_FOUND + X11_XShm_INCLUDE_PATH, (in X11_Xext_LIB), X11_XShm_FOUND + X11_Xshape_INCLUDE_PATH, (in X11_Xext_LIB), X11_Xshape_FOUND + X11_XSync_INCLUDE_PATH, (in X11_Xext_LIB), X11_XSync_FOUND + X11_Xaw_INCLUDE_PATH, X11_Xaw_LIB X11_Xaw_FOUND X11::Xaw .. versionadded:: 3.14 Renamed ``Xxf86misc``, ``X11_Xxf86misc``, ``X11_Xxf86vm``, ``X11_xkbfile``, @@ -92,7 +114,12 @@ and also the following more fine grained variables and targets: Added the ``xcb_randr``, ``xcb_xtext``, and ``xcb_keysyms`` libraries. .. versionadded:: 3.27 - Added the ``xcb_cursor``, ``xcb_shape``, and ``xcb_xrm`` libraries. + Added the ``xcb_composite``, ``xcb_cursor``, ``xcb_damage``, ``xcb_dpms``, + ``xcb_dri2``, ``xcb_dri3``, ``xcb_errors``, ``xcb_ewmh``, ``xcb_glx``, + ``xcb_image``, ``xcb_present``, ``xcb_record``, ``xcb_render``, + ``xcb_render_util``, ``xcb_res``, ``xcb_screensaver``, ``xcb_shape``, + ``xcb_shm``, ``xcb_sync``, ``xcb_xf86dri``, ``xcb_xinerama``, ``xcb_xinput``, + ``xcb_xrm``, ``xcb_xvmc``, and ``xcb_xv`` libraries. #]=======================================================================] @@ -135,18 +162,41 @@ if (UNIX) find_path(X11_Xaccessrules_INCLUDE_PATH X11/extensions/XKBrules.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xaccessstr_INCLUDE_PATH X11/extensions/XKBstr.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xau_INCLUDE_PATH X11/Xauth.h ${X11_INC_SEARCH_PATH}) - find_path(X11_Xaw_INCLUDE_PATH X11/Xaw/Intrinsic.h ${X11_INC_SEARCH_PATH}) + find_path(X11_Xaw_INCLUDE_PATH X11/Xaw/Box.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_INCLUDE_PATH xcb/xcb.h ${X11_INC_SEARCH_PATH}) find_path(X11_X11_xcb_INCLUDE_PATH X11/Xlib-xcb.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_composite_INCLUDE_PATH xcb/composite.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_cursor_INCLUDE_PATH xcb/xcb_cursor.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_damage_INCLUDE_PATH xcb/damage.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_dpms_INCLUDE_PATH xcb/dpms.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_dri2_INCLUDE_PATH xcb/dri2.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_dri3_INCLUDE_PATH xcb/dri3.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_errors_INCLUDE_PATH xcb/xcb_errors.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_ewmh_INCLUDE_PATH xcb/xcb_ewmh.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_glx_INCLUDE_PATH xcb/glx.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_icccm_INCLUDE_PATH xcb/xcb_icccm.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_image_INCLUDE_PATH xcb/xcb_image.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_keysyms_INCLUDE_PATH xcb/xcb_keysyms.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_present_INCLUDE_PATH xcb/present.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_randr_INCLUDE_PATH xcb/randr.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_record_INCLUDE_PATH xcb/record.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_render_INCLUDE_PATH xcb/render.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_render_util_INCLUDE_PATH xcb/xcb_renderutil.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_res_INCLUDE_PATH xcb/res.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_screensaver_INCLUDE_PATH xcb/screensaver.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_shape_INCLUDE_PATH xcb/shape.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_shm_INCLUDE_PATH xcb/shm.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_sync_INCLUDE_PATH xcb/sync.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_util_INCLUDE_PATH xcb/xcb_aux.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xf86dri_INCLUDE_PATH xcb/xf86dri.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_xfixes_INCLUDE_PATH xcb/xfixes.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xinerama_INCLUDE_PATH xcb/xinerama.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xinput_INCLUDE_PATH xcb/xinput.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xkb_INCLUDE_PATH xcb/xkb.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_xrm_INCLUDE_PATH xcb/xcb_xrm.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_xtest_INCLUDE_PATH xcb/xtest.h ${X11_INC_SEARCH_PATH}) - find_path(X11_xcb_keysyms_INCLUDE_PATH xcb/xcb_keysyms.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xvmc_INCLUDE_PATH xcb/xvmc.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xv_INCLUDE_PATH xcb/xv.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xcomposite_INCLUDE_PATH X11/extensions/Xcomposite.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xcursor_INCLUDE_PATH X11/Xcursor/Xcursor.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xdamage_INCLUDE_PATH X11/extensions/Xdamage.h ${X11_INC_SEARCH_PATH}) @@ -191,45 +241,67 @@ if (UNIX) find_library(X11_X11_LIB X11 ${X11_LIB_SEARCH_PATH}) # Find additional X libraries. Keep list sorted by library name. - find_library(X11_ICE_LIB ICE ${X11_LIB_SEARCH_PATH}) - find_library(X11_SM_LIB SM ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xau_LIB Xau ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xaw_LIB Xaw ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_LIB xcb ${X11_LIB_SEARCH_PATH}) - find_library(X11_X11_xcb_LIB X11-xcb ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_cursor_LIB xcb-cursor ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_icccm_LIB xcb-icccm ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_randr_LIB xcb-randr ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_shape_LIB xcb-shape ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_util_LIB xcb-util ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_xfixes_LIB xcb-xfixes ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_xrm_LIB xcb-xrm ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_xtest_LIB xcb-xtest ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_keysyms_LIB xcb-keysyms ${X11_LIB_SEARCH_PATH}) - find_library(X11_xcb_xkb_LIB xcb-xkb ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xcomposite_LIB Xcomposite ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xcursor_LIB Xcursor ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xdamage_LIB Xdamage ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xdmcp_LIB Xdmcp ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xext_LIB Xext ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xfixes_LIB Xfixes ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xft_LIB Xft ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xi_LIB Xi ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xinerama_LIB Xinerama ${X11_LIB_SEARCH_PATH}) - find_library(X11_xkbcommon_LIB xkbcommon ${X11_LIB_SEARCH_PATH}) - find_library(X11_xkbcommon_X11_LIB xkbcommon-x11 ${X11_LIB_SEARCH_PATH}) - find_library(X11_xkbfile_LIB xkbfile ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xmu_LIB Xmu ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xpm_LIB Xpm ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xrandr_LIB Xrandr ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH}) - find_library(X11_XRes_LIB XRes ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xss_LIB Xss ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xt_LIB Xt ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xtst_LIB Xtst ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xv_LIB Xv ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xxf86misc_LIB Xxf86misc ${X11_LIB_SEARCH_PATH}) - find_library(X11_Xxf86vm_LIB Xxf86vm ${X11_LIB_SEARCH_PATH}) + find_library(X11_ICE_LIB ICE ${X11_LIB_SEARCH_PATH}) + find_library(X11_SM_LIB SM ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xau_LIB Xau ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xaw_LIB Xaw ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_LIB xcb ${X11_LIB_SEARCH_PATH}) + find_library(X11_X11_xcb_LIB X11-xcb ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_composite_LIB xcb-composite ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_cursor_LIB xcb-cursor ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_damage_LIB xcb-damage ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_dpms_LIB xcb-dpms ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_dri2_LIB xcb-dri2 ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_dri3_LIB xcb-dri3 ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_errors_LIB xcb-errors ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_ewmh_LIB xcb-ewmh ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_glx_LIB xcb-glx ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_icccm_LIB xcb-icccm ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_image_LIB xcb-image ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_keysyms_LIB xcb-keysyms ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_present_LIB xcb-present ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_randr_LIB xcb-randr ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_record_LIB xcb-record ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_render_LIB xcb-render ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_render_util_LIB xcb-render-util ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_res_LIB xcb-res ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_screensaver_LIB xcb-screensaver ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_shape_LIB xcb-shape ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_shm_LIB xcb-shm ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_sync_LIB xcb-sync ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_util_LIB xcb-util ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xf86dri_LIB xcb-xf86dri ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xfixes_LIB xcb-xfixes ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xinerama_LIB xcb-xinerama ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xinput_LIB xcb-xinput ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xkb_LIB xcb-xkb ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xrm_LIB xcb-xrm ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xtest_LIB xcb-xtest ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xvmc_LIB xcb-xvmc ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xv_LIB xcb-xv ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xcomposite_LIB Xcomposite ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xcursor_LIB Xcursor ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xdamage_LIB Xdamage ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xdmcp_LIB Xdmcp ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xext_LIB Xext ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xfixes_LIB Xfixes ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xft_LIB Xft ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xi_LIB Xi ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xinerama_LIB Xinerama ${X11_LIB_SEARCH_PATH}) + find_library(X11_xkbcommon_LIB xkbcommon ${X11_LIB_SEARCH_PATH}) + find_library(X11_xkbcommon_X11_LIB xkbcommon-x11 ${X11_LIB_SEARCH_PATH}) + find_library(X11_xkbfile_LIB xkbfile ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xmu_LIB Xmu ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xpm_LIB Xpm ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xrandr_LIB Xrandr ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH}) + find_library(X11_XRes_LIB XRes ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xss_LIB Xss ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xt_LIB Xt ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xtst_LIB Xtst ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xv_LIB Xv ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xxf86misc_LIB Xxf86misc ${X11_LIB_SEARCH_PATH}) + find_library(X11_Xxf86vm_LIB Xxf86vm ${X11_LIB_SEARCH_PATH}) # Backwards compatibility. set(X11_Xinput_LIB "${X11_Xi_LIB}") @@ -301,44 +373,132 @@ if (UNIX) set(X11_X11_xcb_FOUND TRUE) endif () + if (X11_xcb_composite_LIB AND X11_xcb_composite_INCLUDE_PATH) + set(X11_xcb_composite_FOUND TRUE) + endif () + if (X11_xcb_cursor_LIB AND X11_xcb_cursor_INCLUDE_PATH) set(X11_xcb_cursor_FOUND TRUE) endif () + if (X11_xcb_damage_LIB AND X11_xcb_damage_INCLUDE_PATH) + set(X11_xcb_damage_FOUND TRUE) + endif () + + if (X11_xcb_dpms_LIB AND X11_xcb_dpms_INCLUDE_PATH) + set(X11_xcb_dpms_FOUND TRUE) + endif () + + if (X11_xcb_dri2_LIB AND X11_xcb_dri2_INCLUDE_PATH) + set(X11_xcb_dri2_FOUND TRUE) + endif () + + if (X11_xcb_dri3_LIB AND X11_xcb_dri3_INCLUDE_PATH) + set(X11_xcb_dri3_FOUND TRUE) + endif () + + if (X11_xcb_errors_LIB AND X11_xcb_errors_INCLUDE_PATH) + set(X11_xcb_errors_FOUND TRUE) + endif () + + if (X11_xcb_ewmh_LIB AND X11_xcb_ewmh_INCLUDE_PATH) + set(X11_xcb_ewmh_FOUND TRUE) + endif () + + if (X11_xcb_glx_LIB AND X11_xcb_glx_INCLUDE_PATH) + set(X11_xcb_glx_FOUND TRUE) + endif () + if (X11_xcb_icccm_LIB AND X11_xcb_icccm_INCLUDE_PATH) set(X11_xcb_icccm_FOUND TRUE) endif () + if (X11_xcb_image_LIB AND X11_xcb_image_INCLUDE_PATH) + set(X11_xcb_image_FOUND TRUE) + endif () + + if (X11_xcb_keysyms_LIB AND X11_xcb_keysyms_INCLUDE_PATH) + set(X11_xcb_keysyms_FOUND TRUE) + endif () + + if (X11_xcb_present_LIB AND X11_xcb_present_INCLUDE_PATH) + set(X11_xcb_present_FOUND TRUE) + endif () + if (X11_xcb_randr_LIB AND X11_xcb_randr_INCLUDE_PATH) set(X11_xcb_randr_FOUND TRUE) endif () + if (X11_xcb_record_LIB AND X11_xcb_record_INCLUDE_PATH) + set(X11_xcb_record_FOUND TRUE) + endif () + + if (X11_xcb_render_LIB AND X11_xcb_render_INCLUDE_PATH) + set(X11_xcb_render_FOUND TRUE) + endif () + + if (X11_xcb_render_util_LIB AND X11_xcb_render_util_INCLUDE_PATH) + set(X11_xcb_render_util_FOUND TRUE) + endif () + + if (X11_xcb_res_LIB AND X11_xcb_res_INCLUDE_PATH) + set(X11_xcb_res_FOUND TRUE) + endif () + + if (X11_xcb_screensaver_LIB AND X11_xcb_screensaver_INCLUDE_PATH) + set(X11_xcb_screensaver_FOUND TRUE) + endif () + if (X11_xcb_shape_LIB AND X11_xcb_shape_INCLUDE_PATH) set(X11_xcb_shape_FOUND TRUE) endif () + if (X11_xcb_shm_LIB AND X11_xcb_shm_INCLUDE_PATH) + set(X11_xcb_shm_FOUND TRUE) + endif () + + if (X11_xcb_sync_LIB AND X11_xcb_sync_INCLUDE_PATH) + set(X11_xcb_sync_FOUND TRUE) + endif () + if (X11_xcb_util_LIB AND X11_xcb_util_INCLUDE_PATH) set(X11_xcb_util_FOUND TRUE) endif () - if (X11_xcb_xfixes_LIB) + if (X11_xcb_xf86dri_LIB AND X11_xcb_xf86dri_INCLUDE_PATH) + set(X11_xcb_xf86dri_FOUND TRUE) + endif () + + if (X11_xcb_xfixes_LIB AND X11_xcb_xfixes_INCLUDE_PATH) set(X11_xcb_xfixes_FOUND TRUE) endif () + if (X11_xcb_xinerama_LIB AND X11_xcb_xinerama_INCLUDE_PATH) + set(X11_xcb_xinerama_FOUND TRUE) + endif () + + if (X11_xcb_xinput_LIB AND X11_xcb_xinput_INCLUDE_PATH) + set(X11_xcb_xinput_FOUND TRUE) + endif () + + if (X11_xcb_xkb_LIB AND X11_xcb_xkb_INCLUDE_PATH) + set(X11_xcb_xkb_FOUND TRUE) + endif () + if (X11_xcb_xrm_LIB AND X11_xcb_xrm_INCLUDE_PATH) set(X11_xcb_xrm_FOUND TRUE) endif () - if (X11_xcb_xtest_LIB) + if (X11_xcb_xtest_LIB AND X11_xcb_xtest_INCLUDE_PATH) set(X11_xcb_xtest_FOUND TRUE) endif () - if (X11_xcb_keysyms_LIB) - set(X11_xcb_keysyms_FOUND TRUE) + if (X11_xcb_xvmc_LIB AND X11_xcb_xvmc_INCLUDE_PATH) + set(X11_xcb_xvmc_FOUND TRUE) endif () - if (X11_xcb_xkb_LIB) - set(X11_xcb_xkb_FOUND TRUE) + if (X11_xcb_xv_LIB AND X11_xcb_xv_INCLUDE_PATH) + set(X11_xcb_xv_FOUND TRUE) endif () if (X11_Xdmcp_INCLUDE_PATH AND X11_Xdmcp_LIB) @@ -641,6 +801,13 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb;X11::X11") endif () + if (X11_xcb_composite_FOUND AND NOT TARGET X11::xcb_composite) + add_library(X11::xcb_composite UNKNOWN IMPORTED) + set_target_properties(X11::xcb_composite PROPERTIES + IMPORTED_LOCATION "${X11_xcb_composite_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_cursor_FOUND AND NOT TARGET X11::xcb_cursor) add_library(X11::xcb_cursor UNKNOWN IMPORTED) set_target_properties(X11::xcb_cursor PROPERTIES @@ -648,6 +815,55 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_damage_FOUND AND NOT TARGET X11::xcb_damage) + add_library(X11::xcb_damage UNKNOWN IMPORTED) + set_target_properties(X11::xcb_damage PROPERTIES + IMPORTED_LOCATION "${X11_xcb_damage_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_dpms_FOUND AND NOT TARGET X11::xcb_dpms) + add_library(X11::xcb_dpms UNKNOWN IMPORTED) + set_target_properties(X11::xcb_dpms PROPERTIES + IMPORTED_LOCATION "${X11_xcb_dpms_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_dri2_FOUND AND NOT TARGET X11::xcb_dri2) + add_library(X11::xcb_dri2 UNKNOWN IMPORTED) + set_target_properties(X11::xcb_dri2 PROPERTIES + IMPORTED_LOCATION "${X11_xcb_dri2_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_dri3_FOUND AND NOT TARGET X11::xcb_dri3) + add_library(X11::xcb_dri3 UNKNOWN IMPORTED) + set_target_properties(X11::xcb_dri3 PROPERTIES + IMPORTED_LOCATION "${X11_xcb_dri3_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_errors_FOUND AND NOT TARGET X11::xcb_errors) + add_library(X11::xcb_errors UNKNOWN IMPORTED) + set_target_properties(X11::xcb_errors PROPERTIES + IMPORTED_LOCATION "${X11_xcb_errors_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_ewmh_FOUND AND NOT TARGET X11::xcb_ewmh) + add_library(X11::xcb_ewmh UNKNOWN IMPORTED) + set_target_properties(X11::xcb_ewmh PROPERTIES + IMPORTED_LOCATION "${X11_xcb_ewmh_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_glx_FOUND AND NOT TARGET X11::xcb_glx) + add_library(X11::xcb_glx UNKNOWN IMPORTED) + set_target_properties(X11::xcb_glx PROPERTIES + IMPORTED_LOCATION "${X11_xcb_glx_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_icccm_FOUND AND NOT TARGET X11::xcb_icccm) add_library(X11::xcb_icccm UNKNOWN IMPORTED) set_target_properties(X11::xcb_icccm PROPERTIES @@ -655,6 +871,27 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_image_FOUND AND NOT TARGET X11::xcb_image) + add_library(X11::xcb_image UNKNOWN IMPORTED) + set_target_properties(X11::xcb_image PROPERTIES + IMPORTED_LOCATION "${X11_xcb_image_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_keysyms_FOUND AND NOT TARGET X11::xcb_keysyms) + add_library(X11::xcb_keysyms UNKNOWN IMPORTED) + set_target_properties(X11::xcb_keysyms PROPERTIES + IMPORTED_LOCATION "${X11_xcb_keysyms_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_present_FOUND AND NOT TARGET X11::xcb_present) + add_library(X11::xcb_present UNKNOWN IMPORTED) + set_target_properties(X11::xcb_present PROPERTIES + IMPORTED_LOCATION "${X11_xcb_present_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_randr_FOUND AND NOT TARGET X11::xcb_randr) add_library(X11::xcb_randr UNKNOWN IMPORTED) set_target_properties(X11::xcb_randr PROPERTIES @@ -662,6 +899,41 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_record_FOUND AND NOT TARGET X11::xcb_record) + add_library(X11::xcb_record UNKNOWN IMPORTED) + set_target_properties(X11::xcb_record PROPERTIES + IMPORTED_LOCATION "${X11_xcb_record_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_render_FOUND AND NOT TARGET X11::xcb_render) + add_library(X11::xcb_render UNKNOWN IMPORTED) + set_target_properties(X11::xcb_render PROPERTIES + IMPORTED_LOCATION "${X11_xcb_render_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_render_util_FOUND AND NOT TARGET X11::xcb_render_util) + add_library(X11::xcb_render_util UNKNOWN IMPORTED) + set_target_properties(X11::xcb_render_util PROPERTIES + IMPORTED_LOCATION "${X11_xcb_render_util_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_res_FOUND AND NOT TARGET X11::xcb_res) + add_library(X11::xcb_res UNKNOWN IMPORTED) + set_target_properties(X11::xcb_res PROPERTIES + IMPORTED_LOCATION "${X11_xcb_res_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_screensaver_FOUND AND NOT TARGET X11::xcb_screensaver) + add_library(X11::xcb_screensaver UNKNOWN IMPORTED) + set_target_properties(X11::xcb_screensaver PROPERTIES + IMPORTED_LOCATION "${X11_xcb_screensaver_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_shape_FOUND AND NOT TARGET X11::xcb_shape) add_library(X11::xcb_shape UNKNOWN IMPORTED) set_target_properties(X11::xcb_shape PROPERTIES @@ -669,6 +941,20 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_shm_FOUND AND NOT TARGET X11::xcb_shm) + add_library(X11::xcb_shm UNKNOWN IMPORTED) + set_target_properties(X11::xcb_shm PROPERTIES + IMPORTED_LOCATION "${X11_xcb_shm_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_sync_FOUND AND NOT TARGET X11::xcb_sync) + add_library(X11::xcb_sync UNKNOWN IMPORTED) + set_target_properties(X11::xcb_sync PROPERTIES + IMPORTED_LOCATION "${X11_xcb_sync_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_util_FOUND AND NOT TARGET X11::xcb_util) add_library(X11::xcb_util UNKNOWN IMPORTED) set_target_properties(X11::xcb_util PROPERTIES @@ -676,6 +962,13 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_xf86dri_FOUND AND NOT TARGET X11::xcb_xf86dri) + add_library(X11::xcb_xf86dri UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xf86dri PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xf86dri_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_xfixes_FOUND AND NOT TARGET X11::xcb_xfixes) add_library(X11::xcb_xfixes UNKNOWN IMPORTED) set_target_properties(X11::xcb_xfixes PROPERTIES @@ -683,6 +976,27 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_xinerama_FOUND AND NOT TARGET X11::xcb_xinerama) + add_library(X11::xcb_xinerama UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xinerama PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xinerama_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_xinput_FOUND AND NOT TARGET X11::xcb_xinput) + add_library(X11::xcb_xinput UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xinput PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xinput_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_xkb_FOUND AND NOT TARGET X11::xcb_xkb) + add_library(X11::xcb_xkb UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xkb PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xkb_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_xrm_FOUND AND NOT TARGET X11::xcb_xrm) add_library(X11::xcb_xrm UNKNOWN IMPORTED) set_target_properties(X11::xcb_xrm PROPERTIES @@ -697,17 +1011,17 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () - if (X11_xcb_keysyms_FOUND AND NOT TARGET X11::xcb_keysyms) - add_library(X11::xcb_keysyms UNKNOWN IMPORTED) - set_target_properties(X11::xcb_keysyms PROPERTIES - IMPORTED_LOCATION "${X11_xcb_keysyms_LIB}" + if (X11_xcb_xvmc_FOUND AND NOT TARGET X11::xcb_xvmc) + add_library(X11::xcb_xvmc UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xvmc PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xvmc_LIB}" INTERFACE_LINK_LIBRARIES "X11::xcb") endif () - if (X11_xcb_xkb_FOUND AND NOT TARGET X11::xcb_xkb) - add_library(X11::xcb_xkb UNKNOWN IMPORTED) - set_target_properties(X11::xcb_xkb PROPERTIES - IMPORTED_LOCATION "${X11_xcb_xkb_LIB}" + if (X11_xcb_xv_FOUND AND NOT TARGET X11::xcb_xv) + add_library(X11::xcb_xv UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xv PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xv_LIB}" INTERFACE_LINK_LIBRARIES "X11::xcb") endif () @@ -918,26 +1232,70 @@ if (UNIX) X11_Xau_INCLUDE_PATH X11_xcb_LIB X11_xcb_INCLUDE_PATH + X11_xcb_composite_LIB + X11_xcb_composite_INCLUDE_PATH X11_xcb_cursor_LIB X11_xcb_cursor_INCLUDE_PATH + X11_xcb_damage_LIB + X11_xcb_damage_INCLUDE_PATH + X11_xcb_dpms_LIB + X11_xcb_dpms_INCLUDE_PATH + X11_xcb_dri2_LIB + X11_xcb_dri2_INCLUDE_PATH + X11_xcb_dri3_LIB + X11_xcb_dri3_INCLUDE_PATH + X11_xcb_errors_LIB + X11_xcb_errors_INCLUDE_PATH + X11_xcb_ewmh_LIB + X11_xcb_ewmh_INCLUDE_PATH + X11_xcb_glx_LIB + X11_xcb_glx_INCLUDE_PATH X11_xcb_icccm_LIB X11_xcb_icccm_INCLUDE_PATH + X11_xcb_image_LIB + X11_xcb_image_INCLUDE_PATH + X11_xcb_keysyms_LIB + X11_xcb_keysyms_INCLUDE_PATH + X11_xcb_present_LIB + X11_xcb_present_INCLUDE_PATH X11_xcb_randr_LIB X11_xcb_randr_INCLUDE_PATH + X11_xcb_record_LIB + X11_xcb_record_INCLUDE_PATH + X11_xcb_render_LIB + X11_xcb_render_INCLUDE_PATH + X11_xcb_render_util_LIB + X11_xcb_render_util_INCLUDE_PATH + X11_xcb_res_LIB + X11_xcb_res_INCLUDE_PATH + X11_xcb_screensaver_LIB + X11_xcb_screensaver_INCLUDE_PATH X11_xcb_shape_LIB X11_xcb_shape_INCLUDE_PATH + X11_xcb_shm_LIB + X11_xcb_shm_INCLUDE_PATH + X11_xcb_sync_LIB + X11_xcb_sync_INCLUDE_PATH X11_xcb_util_LIB X11_xcb_util_INCLUDE_PATH + X11_xcb_xf86dri_LIB + X11_xcb_xf86dri_INCLUDE_PATH X11_xcb_xfixes_LIB X11_xcb_xfixes_INCLUDE_PATH + X11_xcb_xinerama_LIB + X11_xcb_xinerama_INCLUDE_PATH + X11_xcb_xinput_LIB + X11_xcb_xinput_INCLUDE_PATH + X11_xcb_xkb_LIB + X11_X11_xcb_LIB X11_xcb_xrm_LIB X11_xcb_xrm_INCLUDE_PATH X11_xcb_xtest_LIB X11_xcb_xtest_INCLUDE_PATH - X11_xcb_keysyms_LIB - X11_xcb_keysyms_INCLUDE_PATH - X11_xcb_xkb_LIB - X11_X11_xcb_LIB + X11_xcb_xvmc_LIB + X11_xcb_xvmc_INCLUDE_PATH + X11_xcb_xv_LIB + X11_xcb_xv_INCLUDE_PATH X11_X11_xcb_INCLUDE_PATH X11_Xlib_INCLUDE_PATH X11_Xutil_INCLUDE_PATH diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index ed8830ebcd..2c85029ed4 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -373,6 +373,7 @@ function(FortranCInterface_VERIFY) "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}" "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE}" "-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}" + "-DFortranCInterface_BINARY_DIR=${FortranCInterface_BINARY_DIR}" ${_FortranCInterface_OSX_ARCH} ${_FortranCInterface_EXE_LINKER_FLAGS} OUTPUT_VARIABLE _output) diff --git a/Modules/Internal/CPack/ISComponents.pas b/Modules/Internal/CPack/ISComponents.pas new file mode 100644 index 0000000000..8b5c8b4fc2 --- /dev/null +++ b/Modules/Internal/CPack/ISComponents.pas @@ -0,0 +1,88 @@ +{ Distributed under the OSI-approved BSD 3-Clause License. See accompanying +file Copyright.txt or https://cmake.org/licensing for details. } + +function CPackGetCustomInstallationMessage(Param: String): String; +begin + Result := SetupMessage(msgCustomInstallation); +end; + +{ Downloaded components } +#ifdef CPackDownloadCount +const + NO_PROGRESS_BOX = 4; + RESPOND_YES_TO_ALL = 16; +var + CPackDownloadPage: TDownloadWizardPage; + CPackShell: Variant; + +<event('InitializeWizard')> +procedure CPackInitializeWizard(); +begin + CPackDownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil); + CPackShell := CreateOleObject('Shell.Application'); +end; + +<event('NextButtonClick')> +function CPackNextButtonClick(CurPageID: Integer): Boolean; +begin + if CurPageID = wpReady then + begin + CPackDownloadPage.Clear; + CPackDownloadPage.Show; + +#sub AddDownload + if WizardIsComponentSelected('{#CPackDownloadComponents[i]}') then + #emit "CPackDownloadPage.Add('" + CPackDownloadUrls[i] + "', '" + CPackDownloadArchives[i] + ".zip', '" + CPackDownloadHashes[i] + "');" +#endsub +#define i +#for {i = 0; i < CPackDownloadCount; i++} AddDownload +#undef i + + try + try + CPackDownloadPage.Download; + Result := True; + except + if not CPackDownloadPage.AbortedByUser then + SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK); + + Result := False; + end; + finally + CPackDownloadPage.Hide; + end; + end else + Result := True; +end; + +procedure CPackExtractFile(ArchiveName, FileName: String); +var + ZipFileName: String; + ZipFile: Variant; + Item: Variant; + TargetFolderName: String; + TargetFolder: Variant; +begin + TargetFolderName := RemoveBackslashUnlessRoot(ExpandConstant('{tmp}\' + ArchiveName + '\' + ExtractFileDir(FileName))); + ZipFileName := ExpandConstant('{tmp}\' + ArchiveName + '.zip'); + + if not DirExists(TargetFolderName) then + if not ForceDirectories(TargetFolderName) then + RaiseException(Format('Target path "%s" cannot be created', [TargetFolderName])); + + ZipFile := CPackShell.NameSpace(ZipFileName); + if VarIsClear(ZipFile) then + RaiseException(Format('Cannot open ZIP file "%s" or does not exist', [ZipFileName])); + + Item := ZipFile.ParseName(FileName); + if VarIsClear(Item) then + RaiseException(Format('Cannot find "%s" in "%s" ZIP file', [FileName, ZipFileName])); + + TargetFolder := CPackShell.NameSpace(TargetFolderName); + if VarIsClear(TargetFolder) then + RaiseException(Format('Target path "%s" does not exist', [TargetFolderName])); + + TargetFolder.CopyHere(Item, NO_PROGRESS_BOX or RESPOND_YES_TO_ALL); +end; + +#endif diff --git a/Modules/Internal/CPack/ISScript.template.in b/Modules/Internal/CPack/ISScript.template.in new file mode 100644 index 0000000000..1171058939 --- /dev/null +++ b/Modules/Internal/CPack/ISScript.template.in @@ -0,0 +1,34 @@ +; Script generated by the CPack Inno Setup generator. +; All changes made in this file will be lost when CPack is run again. + +@CPACK_INNOSETUP_INCLUDES_INTERNAL@ + +[Setup] +@CPACK_INNOSETUP_SETUP_INTERNAL@ + +[Languages] +@CPACK_INNOSETUP_LANGUAGES_INTERNAL@ + +[Dirs] +@CPACK_INNOSETUP_DIRS_INTERNAL@ + +[Files] +@CPACK_INNOSETUP_FILES_INTERNAL@ + +[Types] +@CPACK_INNOSETUP_TYPES_INTERNAL@ + +[Components] +@CPACK_INNOSETUP_COMPONENTS_INTERNAL@ + +[Tasks] +@CPACK_INNOSETUP_TASKS_INTERNAL@ + +[Icons] +@CPACK_INNOSETUP_ICONS_INTERNAL@ + +[Run] +@CPACK_INNOSETUP_RUN_INTERNAL@ + +[Code] +@CPACK_INNOSETUP_CODE_INTERNAL@ diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index 715f68bb4e..307e4c9a53 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -34,18 +34,26 @@ cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST # If using Android tools for Visual Studio, compile a sample project to get the -# sysroot. +# NDK path and set the processor from the generator platform. if(CMAKE_GENERATOR MATCHES "Visual Studio") - if(NOT CMAKE_SYSROOT) - set(vcx_platform ${CMAKE_GENERATOR_PLATFORM}) - if(CMAKE_GENERATOR MATCHES "Visual Studio 1[45]") - set(vcx_sysroot_var "Sysroot") + if(NOT CMAKE_ANDROID_ARCH_ABI AND NOT CMAKE_SYSTEM_PROCESSOR) + if(CMAKE_GENERATOR_PLATFORM STREQUAL "ARM") + set(CMAKE_SYSTEM_PROCESSOR "armv7-a") + elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + set(CMAKE_SYSTEM_PROCESSOR "aarch64") + elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "x86") + set(CMAKE_SYSTEM_PROCESSOR "i686") + elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "x64") + set(CMAKE_SYSTEM_PROCESSOR "x86_64") else() - set(vcx_sysroot_var "SysrootLink") + message(FATAL_ERROR "Unhandled generator platform, please choose ARM, ARM64, x86 or x86_64 using -A") endif() + endif() + if(NOT CMAKE_ANDROID_NDK) + set(vcx_platform ${CMAKE_GENERATOR_PLATFORM}) if(CMAKE_GENERATOR MATCHES "Visual Studio 14") set(vcx_revision "2.0") - elseif(CMAKE_GENERATOR MATCHES "Visual Studio 1[56]") + elseif(CMAKE_GENERATOR MATCHES "Visual Studio 1[567]") set(vcx_revision "3.0") else() set(vcx_revision "") @@ -62,16 +70,16 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio") RESULT_VARIABLE VCXPROJ_INSPECT_RESULT ) unset(_msbuild) - if(NOT CMAKE_SYSROOT AND VCXPROJ_INSPECT_OUTPUT MATCHES "CMAKE_SYSROOT=([^%\r\n]+)[\r\n]") + if(VCXPROJ_INSPECT_OUTPUT MATCHES "CMAKE_ANDROID_NDK=([^%\r\n]+)[\r\n]") # Strip VS diagnostic output from the end of the line. - string(REGEX REPLACE " \\(TaskId:[0-9]*\\)$" "" _sysroot "${CMAKE_MATCH_1}") - if(EXISTS "${_sysroot}") - file(TO_CMAKE_PATH "${_sysroot}" CMAKE_SYSROOT) + string(REGEX REPLACE " \\(TaskId:[0-9]*\\)$" "" _ndk "${CMAKE_MATCH_1}") + if(EXISTS "${_ndk}") + file(TO_CMAKE_PATH "${_ndk}" CMAKE_ANDROID_NDK) endif() endif() if(VCXPROJ_INSPECT_RESULT) message(CONFIGURE_LOG - "Determining the sysroot for the Android NDK failed. + "Determining the Android NDK failed from msbuild failed. The output was: ${VCXPROJ_INSPECT_RESULT} ${VCXPROJ_INSPECT_OUTPUT} @@ -79,7 +87,7 @@ ${VCXPROJ_INSPECT_OUTPUT} ") else() message(CONFIGURE_LOG - "Determining the sysroot for the Android NDK succeeded. + "Determining the Android NDK succeeded. The output was: ${VCXPROJ_INSPECT_RESULT} ${VCXPROJ_INSPECT_OUTPUT} diff --git a/Modules/Platform/Android/VCXProjInspect.vcxproj.in b/Modules/Platform/Android/VCXProjInspect.vcxproj.in index 6919d2cd85..f87d59bca2 100644 --- a/Modules/Platform/Android/VCXProjInspect.vcxproj.in +++ b/Modules/Platform/Android/VCXProjInspect.vcxproj.in @@ -19,6 +19,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@vcx_platform@'" Label="Configuration"> <ConfigurationType>DynamicLibrary</ConfigurationType> <CharacterSet>MultiByte</CharacterSet> + <AndroidAPILevel>android-21</AndroidAPILevel> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -29,7 +30,7 @@ </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@vcx_platform@'"> <PostBuildEvent> - <Command>%40echo CMAKE_SYSROOT=$(@vcx_sysroot_var@)</Command> + <Command>%40echo CMAKE_ANDROID_NDK=$(VS_NdkRoot)</Command> </PostBuildEvent> </ItemDefinitionGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 4a7d9bc591..2354f3d999 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1018,6 +1018,7 @@ add_library( CPack/cmCPackGeneratorFactory.cxx CPack/cmCPackGenerator.cxx CPack/cmCPackLog.cxx + CPack/cmCPackInnoSetupGenerator.cxx CPack/cmCPackNSISGenerator.cxx CPack/cmCPackNuGetGenerator.cxx CPack/cmCPackSTGZGenerator.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 34eb248804..524f706433 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 20230411) +set(CMake_VERSION_PATCH 20230505) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index 5d995c335d..4a868ae88f 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -5,12 +5,11 @@ #include <cstddef> // IWYU pragma: keep #include <sstream> #include <utility> -#include <vector> #include "cmCPackGenerator.h" #include "cmCPackIFWGenerator.h" #include "cmCPackLog.h" // IWYU pragma: keep -#include "cmStringAlgorithms.h" +#include "cmList.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmVersionConfig.h" @@ -76,13 +75,13 @@ bool cmCPackIFWCommon::IsVersionEqual(const char* version) const void cmCPackIFWCommon::ExpandListArgument( const std::string& arg, std::map<std::string, std::string>& argsOut) { - std::vector<std::string> args = cmExpandedList(arg, false); + cmList args{ arg }; if (args.empty()) { return; } - std::size_t i = 0; - std::size_t c = args.size(); + cmList::size_type i = 0; + auto c = args.size(); if (c % 2) { argsOut[""] = args[i]; ++i; @@ -97,13 +96,13 @@ void cmCPackIFWCommon::ExpandListArgument( void cmCPackIFWCommon::ExpandListArgument( const std::string& arg, std::multimap<std::string, std::string>& argsOut) { - std::vector<std::string> args = cmExpandedList(arg, false); + cmList args{ arg }; if (args.empty()) { return; } - std::size_t i = 0; - std::size_t c = args.size(); + cmList::size_type i = 0; + auto c = args.size(); if (c % 2) { argsOut.insert(std::pair<std::string, std::string>("", args[i])); ++i; diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index bc14eb40b1..5724175510 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -14,6 +14,7 @@ #include "cmCPackLog.h" // IWYU pragma: keep #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -409,8 +410,8 @@ int cmCPackIFWGenerator::InitializeInternal() // Repositories if (cmValue RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { - std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr); - for (std::string const& r : RepoAllVector) { + cmList RepoAllList{ RepoAllStr }; + for (std::string const& r : RepoAllList) { this->GetRepository(r); } } diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 69440d9748..a77c22fa81 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -12,6 +12,7 @@ #include "cmCPackIFWRepository.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 1668fb5d56..083f1ef7b1 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -15,6 +15,7 @@ #include "cmCPackIFWInstaller.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" @@ -427,16 +428,16 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) } // QtIFW dependencies - std::vector<std::string> deps; + cmList deps; option = prefix + "DEPENDS"; if (cmValue value = this->GetOption(option)) { - cmExpandList(value, deps); + deps.assign(value); } option = prefix + "DEPENDENCIES"; if (cmValue value = this->GetOption(option)) { - cmExpandList(value, deps); + deps.append(value); } - for (std::string const& d : deps) { + for (auto const& d : deps) { DependenceStruct dep(d); if (this->Generator->Packages.count(dep.Name)) { cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name]; @@ -455,7 +456,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) if (this->IsSetToEmpty(option)) { this->AlienAutoDependOn.clear(); } else if (cmValue value = this->GetOption(option)) { - std::vector<std::string> depsOn = cmExpandedList(value); + cmList depsOn{ value }; for (std::string const& d : depsOn) { DependenceStruct dep(d); if (this->Generator->Packages.count(dep.Name)) { diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index aeb3db3539..1ea78fdc3d 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -18,6 +18,7 @@ #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUuid.h" @@ -239,7 +240,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() cmValue patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if (patchFilePath) { - std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath); + cmList patchFilePaths{ patchFilePath }; for (std::string const& p : patchFilePaths) { if (!this->Patch->LoadFragments(p)) { @@ -322,8 +323,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) if (!cpackWixExtraObjects) return; - std::vector<std::string> expandedExtraObjects = - cmExpandedList(cpackWixExtraObjects); + cmList expandedExtraObjects{ cpackWixExtraObjects }; for (std::string const& obj : expandedExtraObjects) { stream << " " << QuotePath(obj); @@ -681,10 +681,10 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( featureDefinitions.BeginElement("FeatureRef"); featureDefinitions.AddAttribute("Id", featureId); - std::vector<std::string> cpackPackageExecutablesList; + cmList cpackPackageExecutablesList; cmValue cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { - cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList); + cpackPackageExecutablesList.assign(cpackPackageExecutables); if (cpackPackageExecutablesList.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -695,10 +695,10 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( } } - std::vector<std::string> cpackPackageDesktopLinksList; + cmList cpackPackageDesktopLinksList; cmValue cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS"); if (cpackPackageDesktopLinks) { - cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList); + cpackPackageDesktopLinksList.assign(cpackPackageDesktopLinks); } AddDirectoryAndFileDefinitions( @@ -1160,7 +1160,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, if (!variableContent) return; - std::vector<std::string> list = cmExpandedList(variableContent); + cmList list{ variableContent }; extensions.insert(list.begin(), list.end()); } @@ -1172,7 +1172,7 @@ void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, return; } - std::vector<std::string> list = cmExpandedList(variableContent); + cmList list{ variableContent }; for (std::string const& str : list) { auto pos = str.find('='); if (pos != std::string::npos) { @@ -1200,7 +1200,7 @@ void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, if (!variableContent) return; - std::vector<std::string> list = cmExpandedList(variableContent); + cmList list{ variableContent }; for (std::string const& i : list) { stream << " " << QuotePath(i); diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx index 9685a7f495..2261a66e0f 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.cxx +++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx @@ -19,10 +19,9 @@ cmWIXAccessControlList::cmWIXAccessControlList( bool cmWIXAccessControlList::Apply() { - std::vector<std::string> entries; - this->InstalledFile.GetPropertyAsList("CPACK_WIX_ACL", entries); + auto entries = this->InstalledFile.GetPropertyAsList("CPACK_WIX_ACL"); - for (std::string const& entry : entries) { + for (auto const& entry : entries) { this->CreatePermissionElement(entry); } diff --git a/Source/CPack/WiX/cmWIXShortcut.cxx b/Source/CPack/WiX/cmWIXShortcut.cxx index cd1988a1cb..c3eb219a9d 100644 --- a/Source/CPack/WiX/cmWIXShortcut.cxx +++ b/Source/CPack/WiX/cmWIXShortcut.cxx @@ -91,10 +91,9 @@ void cmWIXShortcuts::CreateFromProperty(std::string const& propertyName, std::string const& directoryId, cmInstalledFile const& installedFile) { - std::vector<std::string> list; - installedFile.GetPropertyAsList(propertyName, list); + auto list = installedFile.GetPropertyAsList(propertyName); - for (std::string const& label : list) { + for (auto const& label : list) { cmWIXShortcut shortcut; shortcut.label = label; shortcut.workingDirectoryId = directoryId; diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index b3d425aa51..7e6e4737dd 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -6,6 +6,7 @@ #include <vector> #include "cmCPackLog.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -191,7 +192,7 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) cmValue sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES"); - std::vector<std::string> relFiles = cmExpandedList(sign_files); + cmList relFiles{ sign_files }; // sign the files supplied by the user, ie. frameworks. for (auto const& file : relFiles) { diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 6ba28d166c..34c56c9993 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -20,6 +20,7 @@ #include "cmCPackLog.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -427,8 +428,7 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const // default control_tar.ClearPermissions(); - std::vector<std::string> controlExtraList = - cmExpandedList(this->ControlExtra); + cmList controlExtraList{ this->ControlExtra }; for (std::string const& i : controlExtraList) { std::string filenamename = cmsys::SystemTools::GetFilenameName(i); std::string localcopy = this->WorkDir + "/" + filenamename; diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 68e7ba3651..768bfbe08d 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -19,6 +19,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -128,8 +129,7 @@ int cmCPackDragNDropGenerator::InitializeInternal() return 0; } - std::vector<std::string> languages = - cmExpandedList(this->GetOption("CPACK_DMG_SLA_LANGUAGES")); + cmList languages{ this->GetOption("CPACK_DMG_SLA_LANGUAGES") }; if (languages.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_DMG_SLA_LANGUAGES set but empty" << std::endl); @@ -543,9 +543,9 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::string sla_xml = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.xml"); - std::vector<std::string> languages; + cmList languages; if (!oldStyle) { - cmExpandList(cpack_dmg_languages, languages); + languages.assign(cpack_dmg_languages); } std::vector<uint16_t> header_data; @@ -574,7 +574,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, header_data.push_back(0); header_data.push_back(languages.size()); - for (size_t i = 0; i < languages.size(); ++i) { + for (cmList::size_type i = 0; i < languages.size(); ++i) { CFStringRef language_cfstring = CFStringCreateWithCString( nullptr, languages[i].c_str(), kCFStringEncodingUTF8); CFStringRef iso_language = diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 4c92592d03..8ba015c8a6 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -15,8 +15,8 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" +#include "cmList.h" #include "cmMakefile.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -79,7 +79,7 @@ int cmCPackExternalGenerator::PackageFiles() cmValue builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); if (builtPackages) { - cmExpandList(builtPackages, this->packageFileNames, false); + cmExpandList(builtPackages, this->packageFileNames); } } diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index ea7b24b488..0840e33cc8 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -2,15 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackFreeBSDGenerator.h" -#include "cmArchiveWrite.h" -#include "cmCPackArchiveGenerator.h" -#include "cmCPackLog.h" -#include "cmGeneratedFileStream.h" -#include "cmStringAlgorithms.h" -#include "cmSystemTools.h" -#include "cmWorkingDirectory.h" - -// Needed for ::open() and ::stat() #include <algorithm> #include <ostream> #include <utility> @@ -21,6 +12,15 @@ #include <sys/stat.h> +#include "cmArchiveWrite.h" +#include "cmCPackArchiveGenerator.h" +#include "cmCPackLog.h" +#include "cmGeneratedFileStream.h" +#include "cmList.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmWorkingDirectory.h" + // Suffix used to tell libpkg what compression to use static const char FreeBSDPackageCompression[] = "txz"; static const char FreeBSDPackageSuffix_17[] = ".pkg"; @@ -292,8 +292,7 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( manifest << ManifestKeyValue( "desc", var_lookup("CPACK_FREEBSD_PACKAGE_DESCRIPTION")); manifest << ManifestKeyValue("www", var_lookup("CPACK_FREEBSD_PACKAGE_WWW")); - std::vector<std::string> licenses = - cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE")); + cmList licenses{ var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE") }; std::string licenselogic("single"); if (licenses.empty()) { cmSystemTools::SetFatalErrorOccurred(); @@ -302,12 +301,10 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( } manifest << ManifestKeyValue("licenselogic", licenselogic); manifest << (ManifestKeyListValue("licenses") << licenses); - std::vector<std::string> categories = - cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_CATEGORIES")); + cmList categories{ var_lookup("CPACK_FREEBSD_PACKAGE_CATEGORIES") }; manifest << (ManifestKeyListValue("categories") << categories); manifest << ManifestKeyValue("prefix", var_lookup("CMAKE_INSTALL_PREFIX")); - std::vector<std::string> deps = - cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_DEPS")); + cmList deps{ var_lookup("CPACK_FREEBSD_PACKAGE_DEPS") }; if (!deps.empty()) { manifest << (ManifestKeyDepsValue("deps") << deps); } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 2ac5b3dc77..afd85cda75 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -19,6 +19,7 @@ #include "cmFileTimes.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" @@ -216,8 +217,7 @@ int cmCPackGenerator::InstallProject() cmValue default_dir_install_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_install_permissions)) { - std::vector<std::string> items = - cmExpandedList(default_dir_install_permissions); + cmList items{ default_dir_install_permissions }; for (const auto& arg : items) { if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -266,7 +266,7 @@ int cmCPackGenerator::InstallProject() // Run pre-build actions cmValue preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); if (preBuildScripts) { - const auto scripts = cmExpandedList(preBuildScripts, false); + const cmList scripts{ preBuildScripts }; for (const auto& script : scripts) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Executing pre-build script: " << script << std::endl); @@ -296,8 +296,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( std::string tempInstallDirectoryEnv = cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory); cmSystemTools::PutEnv(tempInstallDirectoryEnv); - std::vector<std::string> installCommandsVector = - cmExpandedList(installCommands); + cmList installCommandsVector{ installCommands }; for (std::string const& ic : installCommandsVector) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl); std::string output; @@ -333,8 +332,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( std::vector<cmsys::RegularExpression> ignoreFilesRegex; cmValue cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); if (cpackIgnoreFiles) { - std::vector<std::string> ignoreFilesRegexString = - cmExpandedList(cpackIgnoreFiles); + cmList ignoreFilesRegexString{ cpackIgnoreFiles }; for (std::string const& ifr : ignoreFilesRegexString) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Create ignore files regex for: " << ifr << std::endl); @@ -343,9 +341,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( } cmValue installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); if (cmNonempty(installDirectories)) { - std::vector<std::string> installDirectoriesVector = - cmExpandedList(installDirectories); - if (installDirectoriesVector.size() % 2 != 0) { + cmList installDirectoriesList{ installDirectories }; + if (installDirectoriesList.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> " @@ -355,10 +352,10 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( << std::endl); return 0; } - std::vector<std::string>::iterator it; + cmList::iterator it; const std::string& tempDir = tempInstallDirectory; - for (it = installDirectoriesVector.begin(); - it != installDirectoriesVector.end(); ++it) { + for (it = installDirectoriesList.begin(); + it != installDirectoriesList.end(); ++it) { std::vector<std::pair<std::string, std::string>> symlinkedFiles; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); cmsys::Glob gl; @@ -485,7 +482,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( if (cmakeScripts && !cmakeScripts->empty()) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts << std::endl); - std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts); + cmList cmakeScriptsVector{ cmakeScripts }; for (std::string const& installScript : cmakeScriptsVector) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, @@ -549,14 +546,12 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( << std::endl); return 0; } - std::vector<std::string> cmakeProjectsVector = - cmExpandedList(cmakeProjects); - std::vector<std::string>::iterator it; - for (it = cmakeProjectsVector.begin(); it != cmakeProjectsVector.end(); - ++it) { - if (it + 1 == cmakeProjectsVector.end() || - it + 2 == cmakeProjectsVector.end() || - it + 3 == cmakeProjectsVector.end()) { + cmList cmakeProjectsList{ cmakeProjects }; + cmList::iterator it; + for (it = cmakeProjectsList.begin(); it != cmakeProjectsList.end(); ++it) { + if (it + 1 == cmakeProjectsList.end() || + it + 2 == cmakeProjectsList.end() || + it + 3 == cmakeProjectsList.end()) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Not enough items on list: CPACK_INSTALL_CMAKE_PROJECTS. " @@ -578,7 +573,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( ++it; project.SubDirectory = *it; - std::vector<std::string> componentsVector; + cmList componentsList; bool componentInstall = false; /* @@ -593,10 +588,9 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::string installTypesVar = "CPACK_" + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; cmValue installTypes = this->GetOption(installTypesVar); - if (cmNonempty(installTypes)) { - std::vector<std::string> installTypesVector = - cmExpandedList(installTypes); - for (std::string const& installType : installTypesVector) { + if (!installTypes.IsEmpty()) { + cmList installTypesList{ installTypes }; + for (std::string const& installType : installTypesList) { project.InstallationTypes.push_back( this->GetInstallationType(project.ProjectName, installType)); } @@ -606,23 +600,23 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::string componentsVar = "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); cmValue components = this->GetOption(componentsVar); - if (cmNonempty(components)) { - cmExpandList(components, componentsVector); - for (std::string const& comp : componentsVector) { + if (!components.IsEmpty()) { + componentsList.assign(components); + for (auto const& comp : componentsList) { project.Components.push_back( this->GetComponent(project.ProjectName, comp)); } componentInstall = true; } } - if (componentsVector.empty()) { - componentsVector.push_back(project.Component); + if (componentsList.empty()) { + componentsList.push_back(project.Component); } - std::vector<std::string> buildConfigs; + cmList buildConfigs; // Try get configuration names given via `-C` CLI option - cmExpandList(this->GetOption("CPACK_BUILD_CONFIG"), buildConfigs); + buildConfigs.assign(this->GetOption("CPACK_BUILD_CONFIG")); // Remove duplicates std::sort(buildConfigs.begin(), buildConfigs.end()); @@ -661,7 +655,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( << buildConfig << ']' << std::endl); // Run the installation for each component - for (std::string const& component : componentsVector) { + for (std::string const& component : componentsList) { if (!this->InstallCMakeProject( setDestDir, project.Directory, baseTempInstallDirectory, default_dir_mode, component, componentInstall, @@ -894,9 +888,8 @@ int cmCPackGenerator::InstallCMakeProject( mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); } - std::vector<std::string> custom_variables; - this->MakefileMap->GetDefExpandList("CPACK_CUSTOM_INSTALL_VARIABLES", - custom_variables); + cmList custom_variables{ this->MakefileMap->GetDefinition( + "CPACK_CUSTOM_INSTALL_VARIABLES") }; for (auto const& custom_variable : custom_variables) { std::string value; @@ -1129,7 +1122,7 @@ int cmCPackGenerator::DoPackage() this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES", cmJoin(this->packageFileNames, ";")); - const auto scripts = cmExpandedList(postBuildScripts, false); + const cmList scripts{ postBuildScripts }; for (const auto& script : scripts) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Executing post-build script: " << script << std::endl); @@ -1595,9 +1588,8 @@ cmCPackComponent* cmCPackGenerator::GetComponent( // Determine the installation types. cmValue installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); if (cmNonempty(installTypes)) { - std::vector<std::string> installTypesVector = - cmExpandedList(installTypes); - for (std::string const& installType : installTypesVector) { + cmList installTypesList{ installTypes }; + for (auto const& installType : installTypesList) { component->InstallationTypes.push_back( this->GetInstallationType(projectName, installType)); } @@ -1606,8 +1598,8 @@ cmCPackComponent* cmCPackGenerator::GetComponent( // Determine the component dependencies. cmValue depends = this->GetOption(macroPrefix + "_DEPENDS"); if (cmNonempty(depends)) { - std::vector<std::string> dependsVector = cmExpandedList(depends); - for (std::string const& depend : dependsVector) { + cmList dependsList{ depends }; + for (auto const& depend : dependsList) { cmCPackComponent* child = this->GetComponent(projectName, depend); component->Dependencies.push_back(child); child->ReverseDependencies.push_back(component); diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index efb94b9d8f..6ca48bf938 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -13,6 +13,7 @@ #include "cmCPackDebGenerator.h" #include "cmCPackExternalGenerator.h" #include "cmCPackGenerator.h" +#include "cmCPackInnoSetupGenerator.h" #include "cmCPackLog.h" #include "cmCPackNSISGenerator.h" #include "cmCPackNuGetGenerator.h" @@ -60,6 +61,10 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("STGZ", "Self extracting Tar GZip compression", cmCPackSTGZGenerator::CreateGenerator); } + if (cmCPackInnoSetupGenerator::CanGenerate()) { + this->RegisterGenerator("INNOSETUP", "Inno Setup packages", + cmCPackInnoSetupGenerator::CreateGenerator); + } if (cmCPackNSISGenerator::CanGenerate()) { this->RegisterGenerator("NSIS", "Null Soft Installer", cmCPackNSISGenerator::CreateGenerator); diff --git a/Source/CPack/cmCPackInnoSetupGenerator.cxx b/Source/CPack/cmCPackInnoSetupGenerator.cxx new file mode 100644 index 0000000000..d8825d46b5 --- /dev/null +++ b/Source/CPack/cmCPackInnoSetupGenerator.cxx @@ -0,0 +1,1159 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying +file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmCPackInnoSetupGenerator.h" + +#include <algorithm> +#include <cctype> +#include <cstdlib> +#include <ostream> +#include <stack> +#include <utility> + +#include "cmsys/RegularExpression.hxx" + +#include "cmCPackComponentGroup.h" +#include "cmCPackLog.h" +#include "cmDuration.h" +#include "cmGeneratedFileStream.h" +#include "cmList.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +cmCPackInnoSetupGenerator::cmCPackInnoSetupGenerator() = default; +cmCPackInnoSetupGenerator::~cmCPackInnoSetupGenerator() = default; + +bool cmCPackInnoSetupGenerator::CanGenerate() +{ + // Inno Setup is only available for Windows +#ifdef _WIN32 + return true; +#else + return false; +#endif +} + +int cmCPackInnoSetupGenerator::InitializeInternal() +{ + if (cmIsOn(GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) { + cmCPackLogger(cmCPackLog::LOG_WARNING, + "Inno Setup Generator cannot work with " + "CPACK_INCLUDE_TOPLEVEL_DIRECTORY set. " + "This option will be reset to 0 (for this generator only)." + << std::endl); + SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", nullptr); + } + + std::vector<std::string> path; + +#ifdef _WIN32 + path.push_back("C:\\Program Files (x86)\\Inno Setup 5"); + path.push_back("C:\\Program Files (x86)\\Inno Setup 6"); +#endif + + SetOptionIfNotSet("CPACK_INNOSETUP_EXECUTABLE", "ISCC"); + const std::string& isccPath = cmSystemTools::FindProgram( + GetOption("CPACK_INNOSETUP_EXECUTABLE"), path, false); + + if (isccPath.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find Inno Setup compiler ISCC: " + "likely it is not installed, or not in your PATH" + << std::endl); + + return 0; + } + + const std::string isccCmd = cmStrCat(QuotePath(isccPath), "/?"); + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Test Inno Setup version: " << isccCmd << std::endl); + std::string output; + cmSystemTools::RunSingleCommand(isccCmd, &output, &output, nullptr, nullptr, + this->GeneratorVerbose, cmDuration::zero()); + cmsys::RegularExpression vRex("Inno Setup ([0-9]+)"); + if (!vRex.find(output)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem checking Inno Setup version with command: " + << isccCmd << std::endl + << "Have you downloaded Inno Setup from " + "https://jrsoftware.org/isinfo.php?" + << std::endl); + return 0; + } + + const int isccVersion = atoi(vRex.match(1).c_str()); + const int minIsccVersion = 6; + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "Inno Setup Version: " << isccVersion << std::endl); + + if (isccVersion < minIsccVersion) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPack requires Inno Setup Version 6 or greater. " + "Inno Setup found on the system was: " + << isccVersion << std::endl); + return 0; + } + + SetOption("CPACK_INSTALLER_PROGRAM", isccPath); + + return this->Superclass::InitializeInternal(); +} + +int cmCPackInnoSetupGenerator::PackageFiles() +{ + // Includes + if (IsSet("CPACK_INNOSETUP_EXTRA_SCRIPTS")) { + const cmList extraScripts(GetOption("CPACK_INNOSETUP_EXTRA_SCRIPTS")); + + for (const std::string& i : extraScripts) { + includeDirectives.push_back(cmStrCat( + "#include ", QuotePath(cmSystemTools::CollapseFullPath(i, toplevel)))); + } + } + + // [Languages] section + SetOptionIfNotSet("CPACK_INNOSETUP_LANGUAGES", "english"); + const cmList languages(GetOption("CPACK_INNOSETUP_LANGUAGES")); + for (std::string i : languages) { + cmCPackInnoSetupKeyValuePairs params; + + params["Name"] = Quote(i); + + if (cmSystemTools::LowerCase(i) == "english") { + params["MessagesFile"] = "\"compiler:Default.isl\""; + } else { + i[0] = static_cast<char>(std::toupper(i[0])); + params["MessagesFile"] = cmStrCat("\"compiler:Languages\\", i, ".isl\""); + } + + languageInstructions.push_back(ISKeyValueLine(params)); + } + + if (!Components.empty() && !ProcessComponents()) { + return false; + } + + if (!(ProcessSetupSection() && ProcessFiles())) { + return false; + } + + // [Code] section + if (IsSet("CPACK_INNOSETUP_CODE_FILES")) { + const cmList codeFiles(GetOption("CPACK_INNOSETUP_CODE_FILES")); + + for (const std::string& i : codeFiles) { + codeIncludes.push_back(cmStrCat( + "#include ", QuotePath(cmSystemTools::CollapseFullPath(i, toplevel)))); + } + } + + return ConfigureISScript() && Compile(); +} + +bool cmCPackInnoSetupGenerator::ProcessSetupSection() +{ + if (!RequireOption("CPACK_PACKAGE_INSTALL_REGISTRY_KEY")) { + return false; + } + setupDirectives["AppId"] = GetOption("CPACK_PACKAGE_INSTALL_REGISTRY_KEY"); + + if (!RequireOption("CPACK_PACKAGE_NAME")) { + return false; + } + setupDirectives["AppName"] = GetOption("CPACK_PACKAGE_NAME"); + setupDirectives["UninstallDisplayName"] = GetOption("CPACK_PACKAGE_NAME"); + + if (!RequireOption("CPACK_PACKAGE_VERSION")) { + return false; + } + setupDirectives["AppVersion"] = GetOption("CPACK_PACKAGE_VERSION"); + + if (!RequireOption("CPACK_PACKAGE_VENDOR")) { + return false; + } + setupDirectives["AppPublisher"] = GetOption("CPACK_PACKAGE_VENDOR"); + + if (IsSet("CPACK_PACKAGE_HOMEPAGE_URL")) { + setupDirectives["AppPublisherURL"] = + GetOption("CPACK_PACKAGE_HOMEPAGE_URL"); + setupDirectives["AppSupportURL"] = GetOption("CPACK_PACKAGE_HOMEPAGE_URL"); + setupDirectives["AppUpdatesURL"] = GetOption("CPACK_PACKAGE_HOMEPAGE_URL"); + } + + SetOptionIfNotSet("CPACK_INNOSETUP_IGNORE_LICENSE_PAGE", "OFF"); + if (IsSet("CPACK_RESOURCE_FILE_LICENSE") && + !GetOption("CPACK_INNOSETUP_IGNORE_LICENSE_PAGE").IsOn()) { + setupDirectives["LicenseFile"] = cmSystemTools::ConvertToWindowsOutputPath( + GetOption("CPACK_RESOURCE_FILE_LICENSE")); + } + + SetOptionIfNotSet("CPACK_INNOSETUP_IGNORE_README_PAGE", "ON"); + if (IsSet("CPACK_RESOURCE_FILE_README") && + !GetOption("CPACK_INNOSETUP_IGNORE_README_PAGE").IsOn()) { + setupDirectives["InfoBeforeFile"] = + cmSystemTools::ConvertToWindowsOutputPath( + GetOption("CPACK_RESOURCE_FILE_README")); + } + + SetOptionIfNotSet("CPACK_INNOSETUP_USE_MODERN_WIZARD", "OFF"); + if (GetOption("CPACK_INNOSETUP_USE_MODERN_WIZARD").IsOn()) { + setupDirectives["WizardStyle"] = "modern"; + } else { + setupDirectives["WizardStyle"] = "classic"; + setupDirectives["WizardSmallImageFile"] = + "compiler:WizClassicSmallImage.bmp"; + setupDirectives["WizardImageFile"] = "compiler:WizClassicImage.bmp"; + setupDirectives["SetupIconFile"] = "compiler:SetupClassicIcon.ico"; + } + + if (IsSet("CPACK_INNOSETUP_ICON_FILE")) { + setupDirectives["SetupIconFile"] = + cmSystemTools::ConvertToWindowsOutputPath( + GetOption("CPACK_INNOSETUP_ICON_FILE")); + } + + if (IsSet("CPACK_PACKAGE_ICON")) { + setupDirectives["WizardSmallImageFile"] = + cmSystemTools::ConvertToWindowsOutputPath( + GetOption("CPACK_PACKAGE_ICON")); + } + + if (!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { + return false; + } + SetOptionIfNotSet("CPACK_INNOSETUP_INSTALL_ROOT", "{autopf}"); + setupDirectives["DefaultDirName"] = + cmSystemTools::ConvertToWindowsOutputPath( + cmStrCat(GetOption("CPACK_INNOSETUP_INSTALL_ROOT"), '\\', + GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY"))); + + SetOptionIfNotSet("CPACK_INNOSETUP_ALLOW_CUSTOM_DIRECTORY", "ON"); + if (GetOption("CPACK_INNOSETUP_ALLOW_CUSTOM_DIRECTORY").IsOff()) { + setupDirectives["DisableDirPage"] = "yes"; + } + + SetOptionIfNotSet("CPACK_INNOSETUP_PROGRAM_MENU_FOLDER", + GetOption("CPACK_PACKAGE_NAME")); + if (GetOption("CPACK_INNOSETUP_PROGRAM_MENU_FOLDER") == ".") { + setupDirectives["DisableProgramGroupPage"] = "yes"; + toplevelProgramFolder = true; + } else { + setupDirectives["DefaultGroupName"] = + GetOption("CPACK_INNOSETUP_PROGRAM_MENU_FOLDER"); + toplevelProgramFolder = false; + } + + if (IsSet("CPACK_INNOSETUP_PASSWORD")) { + setupDirectives["Password"] = GetOption("CPACK_INNOSETUP_PASSWORD"); + setupDirectives["Encryption"] = "yes"; + } + + /* + * These directives can only be modified using the + * CPACK_INNOSETUP_SETUP_<directive> variables + */ + setupDirectives["ShowLanguageDialog"] = "auto"; + setupDirectives["AllowNoIcons"] = "yes"; + setupDirectives["Compression"] = "lzma"; + setupDirectives["SolidCompression"] = "yes"; + + // Output file and directory + if (!RequireOption("CPACK_PACKAGE_FILE_NAME")) { + return false; + } + setupDirectives["OutputBaseFilename"] = GetOption("CPACK_PACKAGE_FILE_NAME"); + + if (!RequireOption("CPACK_TOPLEVEL_DIRECTORY")) { + return false; + } + setupDirectives["OutputDir"] = cmSystemTools::ConvertToWindowsOutputPath( + GetOption("CPACK_TOPLEVEL_DIRECTORY")); + + setupDirectives["SourceDir"] = + cmSystemTools::ConvertToWindowsOutputPath(toplevel); + + // Target architecture + if (!RequireOption("CPACK_INNOSETUP_ARCHITECTURE")) { + return false; + } + + const std::string& architecture = GetOption("CPACK_INNOSETUP_ARCHITECTURE"); + if (architecture != "x86" && architecture != "x64" && + architecture != "arm64" && architecture != "ia64") { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_INNOSETUP_ARCHITECTURE must be either x86, x64, " + "arm64 or ia64" + << std::endl); + return false; + } + + // The following directives must not be set to target x86 + if (architecture != "x86") { + setupDirectives["ArchitecturesAllowed"] = architecture; + setupDirectives["ArchitecturesInstallIn64BitMode"] = architecture; + } + + /* + * Handle custom directives (they have higher priority than other variables, + * so they have to be processed after all other variables) + */ + for (const std::string& i : GetOptions()) { + if (cmHasPrefix(i, "CPACK_INNOSETUP_SETUP_")) { + const std::string& directive = + i.substr(cmStrLen("CPACK_INNOSETUP_SETUP_")); + setupDirectives[directive] = GetOption(i); + } + } + + return true; +} + +bool cmCPackInnoSetupGenerator::ProcessFiles() +{ + std::map<std::string, std::string> customFileInstructions; + if (IsSet("CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS")) { + const cmList instructions( + GetOption("CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS")); + if (instructions.size() % 2 != 0) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS should " + "contain pairs of <path> and <instruction>" + << std::endl); + return false; + } + + for (auto it = instructions.begin(); it != instructions.end(); ++it) { + const std::string& key = + QuotePath(cmSystemTools::CollapseFullPath(*it, toplevel)); + customFileInstructions[key] = *(++it); + } + } + + const std::string& iconsPrefix = + toplevelProgramFolder ? "{autoprograms}\\" : "{group}\\"; + + std::map<std::string, std::string> icons; + if (IsSet("CPACK_PACKAGE_EXECUTABLES")) { + const cmList executables(GetOption("CPACK_PACKAGE_EXECUTABLES")); + if (executables.size() % 2 != 0) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_PACKAGE_EXECUTABLES should should contain pairs of " + "<executable> and <text label>" + << std::endl); + return false; + } + + for (auto it = executables.begin(); it != executables.end(); ++it) { + const std::string& key = *it; + icons[key] = *(++it); + } + } + + std::vector<std::string> desktopIcons; + if (IsSet("CPACK_CREATE_DESKTOP_LINKS")) { + cmExpandList(GetOption("CPACK_CREATE_DESKTOP_LINKS"), desktopIcons); + } + + std::vector<std::string> runExecutables; + if (IsSet("CPACK_INNOSETUP_RUN_EXECUTABLES")) { + cmExpandList(GetOption("CPACK_INNOSETUP_RUN_EXECUTABLES"), runExecutables); + } + + for (const std::string& i : files) { + cmCPackInnoSetupKeyValuePairs params; + + std::string toplevelDirectory; + std::string outputDir; + cmCPackComponent* component = nullptr; + std::string componentParam; + if (!Components.empty()) { + const std::string& fileName = cmSystemTools::RelativePath(toplevel, i); + const std::string::size_type pos = fileName.find('/'); + + // Use the custom component install directory if we have one + if (pos != std::string::npos) { + const std::string& componentName = fileName.substr(0, pos); + component = &Components[componentName]; + + toplevelDirectory = + cmSystemTools::CollapseFullPath(componentName, toplevel); + outputDir = CustomComponentInstallDirectory(component); + componentParam = + CreateRecursiveComponentPath(component->Group, component->Name); + + if (component->IsHidden && component->IsDisabledByDefault) { + continue; + } + + if (component->IsHidden) { + componentParam.clear(); + } + } else { + // Don't install component directories + continue; + } + } else { + toplevelDirectory = toplevel; + outputDir = "{app}"; + } + + if (!componentParam.empty()) { + params["Components"] = componentParam; + } + + if (cmSystemTools::FileIsDirectory(i)) { + // Custom instructions replace the automatic generated instructions + if (customFileInstructions.count(QuotePath(i))) { + dirInstructions.push_back(customFileInstructions[QuotePath(i)]); + } else { + std::string destDir = cmSystemTools::ConvertToWindowsOutputPath( + cmStrCat(outputDir, '\\', + cmSystemTools::RelativePath(toplevelDirectory, i))); + cmStripSuffixIfExists(destDir, '\\'); + + params["Name"] = QuotePath(destDir); + + dirInstructions.push_back(ISKeyValueLine(params)); + } + } else { + // Custom instructions replace the automatic generated instructions + if (customFileInstructions.count(QuotePath(i))) { + fileInstructions.push_back(customFileInstructions[QuotePath(i)]); + } else { + std::string destDir = cmSystemTools::ConvertToWindowsOutputPath( + cmStrCat(outputDir, '\\', + cmSystemTools::GetParentDirectory( + cmSystemTools::RelativePath(toplevelDirectory, i)))); + cmStripSuffixIfExists(destDir, '\\'); + + params["DestDir"] = QuotePath(destDir); + + if (component != nullptr && component->IsDownloaded) { + const std::string& archiveName = + cmSystemTools::GetFilenameWithoutLastExtension( + component->ArchiveFile); + const std::string& relativePath = + cmSystemTools::RelativePath(toplevelDirectory, i); + + params["Source"] = + QuotePath(cmStrCat("{tmp}\\", archiveName, '\\', relativePath)); + params["ExternalSize"] = + std::to_string(cmSystemTools::FileLength(i)); + params["Flags"] = "external ignoreversion"; + params["BeforeInstall"] = + cmStrCat("CPackExtractFile('", archiveName, "', '", + cmRemoveQuotes(cmSystemTools::ConvertToWindowsOutputPath( + relativePath)), + "')"); + } else { + params["Source"] = QuotePath(i); + params["Flags"] = "ignoreversion"; + } + + fileInstructions.push_back(ISKeyValueLine(params)); + + // Icon + const std::string& name = + cmSystemTools::GetFilenameWithoutLastExtension(i); + const std::string& extension = + cmSystemTools::GetFilenameLastExtension(i); + if ((extension == ".exe" || extension == ".com") && // only .exe, .com + icons.count(name)) { + cmCPackInnoSetupKeyValuePairs iconParams; + + iconParams["Name"] = QuotePath(cmStrCat(iconsPrefix, icons[name])); + iconParams["Filename"] = + QuotePath(cmStrCat(destDir, '\\', name, extension)); + + if (!componentParam.empty()) { + iconParams["Components"] = componentParam; + } + + iconInstructions.push_back(ISKeyValueLine(iconParams)); + + // Desktop icon + if (std::find(desktopIcons.begin(), desktopIcons.end(), name) != + desktopIcons.end()) { + iconParams["Name"] = + QuotePath(cmStrCat("{autodesktop}\\", icons[name])); + iconParams["Tasks"] = "desktopicon"; + + if (!componentParam.empty() && + std::find(desktopIconComponents.begin(), + desktopIconComponents.end(), + componentParam) == desktopIconComponents.end()) { + desktopIconComponents.push_back(componentParam); + } + iconInstructions.push_back(ISKeyValueLine(iconParams)); + } + + // [Run] section + if (std::find(runExecutables.begin(), runExecutables.end(), name) != + runExecutables.end()) { + cmCPackInnoSetupKeyValuePairs runParams; + + runParams["Filename"] = iconParams["Filename"]; + runParams["Description"] = cmStrCat( + "\"{cm:LaunchProgram,", PrepareForConstant(icons[name]), "}\""); + runParams["Flags"] = "nowait postinstall skipifsilent"; + + if (!componentParam.empty()) { + runParams["Components"] = componentParam; + } + + runInstructions.push_back(ISKeyValueLine(runParams)); + } + } + } + } + } + + // Additional icons + static cmsys::RegularExpression urlRegex( + "^(mailto:|(ftps?|https?|news)://).*$"); + + if (IsSet("CPACK_INNOSETUP_MENU_LINKS")) { + const cmList menuIcons(GetOption("CPACK_INNOSETUP_MENU_LINKS")); + if (menuIcons.size() % 2 != 0) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_INNOSETUP_MENU_LINKS should " + "contain pairs of <shortcut target> and <shortcut label>" + << std::endl); + return false; + } + + for (auto it = menuIcons.begin(); it != menuIcons.end(); ++it) { + const std::string& target = *it; + const std::string& label = *(++it); + cmCPackInnoSetupKeyValuePairs params; + + params["Name"] = QuotePath(cmStrCat(iconsPrefix, label)); + if (urlRegex.find(target)) { + params["Filename"] = Quote(target); + } else { + std::string dir = "{app}"; + std::string componentName; + for (const auto& i : Components) { + if (cmSystemTools::FileExists(cmSystemTools::CollapseFullPath( + cmStrCat(i.second.Name, '\\', target), toplevel))) { + dir = CustomComponentInstallDirectory(&i.second); + componentName = + CreateRecursiveComponentPath(i.second.Group, i.second.Name); + + if (i.second.IsHidden && i.second.IsDisabledByDefault) { + goto continueOuterLoop; + } else if (i.second.IsHidden) { + componentName.clear(); + } + + break; + } + } + + params["Filename"] = QuotePath(cmStrCat(dir, '\\', target)); + + if (!componentName.empty()) { + params["Components"] = componentName; + } + } + + iconInstructions.push_back(ISKeyValueLine(params)); + continueOuterLoop:; + } + } + + SetOptionIfNotSet("CPACK_INNOSETUP_CREATE_UNINSTALL_LINK", "OFF"); + if (GetOption("CPACK_INNOSETUP_CREATE_UNINSTALL_LINK").IsOn()) { + cmCPackInnoSetupKeyValuePairs params; + + params["Name"] = QuotePath( + cmStrCat(iconsPrefix, "{cm:UninstallProgram,", + PrepareForConstant(GetOption("CPACK_PACKAGE_NAME")), '}')); + params["Filename"] = "\"{uninstallexe}\""; + + iconInstructions.push_back(ISKeyValueLine(params)); + } + + return true; +} + +bool cmCPackInnoSetupGenerator::ProcessComponents() +{ + codeIncludes.push_back("{ The following lines are required by CPack because " + "this script uses components }"); + + // Installation types + bool noTypes = true; + std::vector<cmCPackInstallationType*> types(InstallationTypes.size()); + for (auto& i : InstallationTypes) { + noTypes = false; + types[i.second.Index - 1] = &i.second; + } + + std::vector<std::string> allTypes; // For required components + for (cmCPackInstallationType* i : types) { + cmCPackInnoSetupKeyValuePairs params; + + params["Name"] = Quote(i->Name); + params["Description"] = Quote(i->DisplayName); + + allTypes.push_back(i->Name); + typeInstructions.push_back(ISKeyValueLine(params)); + } + + if (!noTypes) { + // Inno Setup requires the "custom" type + cmCPackInnoSetupKeyValuePairs params; + + params["Name"] = "\"custom\""; + params["Description"] = "\"{code:CPackGetCustomInstallationMessage}\""; + params["Flags"] = "iscustom"; + + allTypes.push_back("custom"); + typeInstructions.push_back(ISKeyValueLine(params)); + } + + // Components + std::vector<cmCPackComponent*> downloadedComponents; + std::stack<cmCPackComponentGroup*> groups; + for (auto& i : Components) { + cmCPackInnoSetupKeyValuePairs params; + cmCPackComponent* component = &i.second; + + if (component->IsHidden) { + continue; + } + + CreateRecursiveComponentGroups(component->Group); + + params["Name"] = + Quote(CreateRecursiveComponentPath(component->Group, component->Name)); + params["Description"] = Quote(component->DisplayName); + + if (component->IsRequired) { + params["Types"] = cmJoin(allTypes, " "); + params["Flags"] = "fixed"; + } else if (!component->InstallationTypes.empty()) { + std::vector<std::string> installationTypes; + + for (cmCPackInstallationType* j : component->InstallationTypes) { + installationTypes.push_back(j->Name); + } + + params["Types"] = cmJoin(installationTypes, " "); + } + + componentInstructions.push_back(ISKeyValueLine(params)); + + if (component->IsDownloaded) { + downloadedComponents.push_back(component); + + if (component->ArchiveFile.empty()) { + // Compute the name of the archive. + if (!RequireOption("CPACK_TEMPORARY_DIRECTORY")) { + return false; + } + + std::string packagesDir = + cmStrCat(GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy"); + component->ArchiveFile = + cmStrCat(cmSystemTools::GetFilenameWithoutLastExtension(packagesDir), + '-', component->Name, ".zip"); + } else if (!cmHasSuffix(component->ArchiveFile, ".zip")) { + component->ArchiveFile = cmStrCat(component->ArchiveFile, ".zip"); + } + } + } + + // Downloaded components + if (!downloadedComponents.empty()) { + // Create the directory for the upload area + cmValue userUploadDirectory = GetOption("CPACK_UPLOAD_DIRECTORY"); + std::string uploadDirectory; + if (cmNonempty(userUploadDirectory)) { + uploadDirectory = *userUploadDirectory; + } else { + if (!RequireOption("CPACK_PACKAGE_DIRECTORY")) { + return false; + } + + uploadDirectory = + cmStrCat(GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads"); + } + + if (!cmSystemTools::FileExists(uploadDirectory)) { + if (!cmSystemTools::MakeDirectory(uploadDirectory)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Unable to create Inno Setup upload directory " + << uploadDirectory << std::endl); + return false; + } + } + + if (!RequireOption("CPACK_DOWNLOAD_SITE")) { + return false; + } + + SetOptionIfNotSet("CPACK_INNOSETUP_VERIFY_DOWNLOADS", "ON"); + const bool verifyDownloads = + GetOption("CPACK_INNOSETUP_VERIFY_DOWNLOADS").IsOn(); + + const std::string& urlPrefix = + cmHasSuffix(GetOption("CPACK_DOWNLOAD_SITE").GetCStr(), '/') + ? GetOption("CPACK_DOWNLOAD_SITE") + : cmStrCat(GetOption("CPACK_DOWNLOAD_SITE"), '/'); + + std::vector<std::string> archiveUrls; + std::vector<std::string> archiveFiles; + std::vector<std::string> archiveHashes; + std::vector<std::string> archiveComponents; + for (cmCPackComponent* i : downloadedComponents) { + std::string hash; + if (!BuildDownloadedComponentArchive( + i, uploadDirectory, (verifyDownloads ? &hash : nullptr))) { + return false; + } + + archiveUrls.push_back(Quote(cmStrCat(urlPrefix, i->ArchiveFile))); + archiveFiles.push_back( + Quote(cmSystemTools::GetFilenameWithoutLastExtension(i->ArchiveFile))); + archiveHashes.push_back(Quote(hash)); + archiveComponents.push_back( + Quote(CreateRecursiveComponentPath(i->Group, i->Name))); + } + + SetOption("CPACK_INNOSETUP_DOWNLOAD_COUNT_INTERNAL", + std::to_string(archiveFiles.size())); + SetOption("CPACK_INNOSETUP_DOWNLOAD_URLS_INTERNAL", + cmJoin(archiveUrls, ", ")); + SetOption("CPACK_INNOSETUP_DOWNLOAD_ARCHIVES_INTERNAL", + cmJoin(archiveFiles, ", ")); + SetOption("CPACK_INNOSETUP_DOWNLOAD_HASHES_INTERNAL", + cmJoin(archiveHashes, ", ")); + SetOption("CPACK_INNOSETUP_DOWNLOAD_COMPONENTS_INTERNAL", + cmJoin(archiveComponents, ", ")); + + static const std::string& downloadLines = + "#define protected CPackDownloadCount " + "@CPACK_INNOSETUP_DOWNLOAD_COUNT_INTERNAL@\n" + "#dim protected CPackDownloadUrls[CPackDownloadCount] " + "{@CPACK_INNOSETUP_DOWNLOAD_URLS_INTERNAL@}\n" + "#dim protected CPackDownloadArchives[CPackDownloadCount] " + "{@CPACK_INNOSETUP_DOWNLOAD_ARCHIVES_INTERNAL@}\n" + "#dim protected CPackDownloadHashes[CPackDownloadCount] " + "{@CPACK_INNOSETUP_DOWNLOAD_HASHES_INTERNAL@}\n" + "#dim protected CPackDownloadComponents[CPackDownloadCount] " + "{@CPACK_INNOSETUP_DOWNLOAD_COMPONENTS_INTERNAL@}"; + + std::string output; + if (!ConfigureString(downloadLines, output)) { + return false; + } + codeIncludes.push_back(output); + } + + // Add the required script + const std::string& componentsScriptTemplate = + FindTemplate("ISComponents.pas"); + if (componentsScriptTemplate.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Could not find additional Inno Setup script file." + << std::endl); + return false; + } + + codeIncludes.push_back("#include " + QuotePath(componentsScriptTemplate) + + "\n"); + + return true; +} + +bool cmCPackInnoSetupGenerator::ConfigureISScript() +{ + const std::string& isScriptTemplate = FindTemplate("ISScript.template.in"); + const std::string& isScriptFile = + cmStrCat(GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/ISScript.iss"); + + if (isScriptTemplate.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Could not find Inno Setup installer template file." + << std::endl); + return false; + } + + // Create internal variables + std::vector<std::string> setupSection; + for (const auto& i : setupDirectives) { + setupSection.push_back(cmStrCat(i.first, '=', TranslateBool(i.second))); + } + + // Also create comments if the sections are empty + const std::string& defaultMessage = + "; CPack didn't find any entries for this section"; + + if (IsSet("CPACK_CREATE_DESKTOP_LINKS") && + !GetOption("CPACK_CREATE_DESKTOP_LINKS").Get()->empty()) { + cmCPackInnoSetupKeyValuePairs tasks; + tasks["Name"] = "\"desktopicon\""; + tasks["Description"] = "\"{cm:CreateDesktopIcon}\""; + tasks["GroupDescription"] = "\"{cm:AdditionalIcons}\""; + tasks["Flags"] = "unchecked"; + + if (!desktopIconComponents.empty()) { + tasks["Components"] = cmJoin(desktopIconComponents, " "); + } + + SetOption("CPACK_INNOSETUP_TASKS_INTERNAL", ISKeyValueLine(tasks)); + } else { + SetOption("CPACK_INNOSETUP_TASKS_INTERNAL", defaultMessage); + } + + SetOption("CPACK_INNOSETUP_INCLUDES_INTERNAL", + includeDirectives.empty() ? "; No extra script files specified" + : cmJoin(includeDirectives, "\n")); + SetOption("CPACK_INNOSETUP_SETUP_INTERNAL", + setupSection.empty() ? defaultMessage + : cmJoin(setupSection, "\n")); + SetOption("CPACK_INNOSETUP_LANGUAGES_INTERNAL", + languageInstructions.empty() ? defaultMessage + : cmJoin(languageInstructions, "\n")); + SetOption("CPACK_INNOSETUP_DIRS_INTERNAL", + dirInstructions.empty() ? defaultMessage + : cmJoin(dirInstructions, "\n")); + SetOption("CPACK_INNOSETUP_FILES_INTERNAL", + fileInstructions.empty() ? defaultMessage + : cmJoin(fileInstructions, "\n")); + SetOption("CPACK_INNOSETUP_TYPES_INTERNAL", + typeInstructions.empty() ? defaultMessage + : cmJoin(typeInstructions, "\n")); + SetOption("CPACK_INNOSETUP_COMPONENTS_INTERNAL", + componentInstructions.empty() + ? defaultMessage + : cmJoin(componentInstructions, "\n")); + SetOption("CPACK_INNOSETUP_ICONS_INTERNAL", + iconInstructions.empty() ? defaultMessage + : cmJoin(iconInstructions, "\n")); + SetOption("CPACK_INNOSETUP_RUN_INTERNAL", + runInstructions.empty() ? defaultMessage + : cmJoin(runInstructions, "\n")); + SetOption("CPACK_INNOSETUP_CODE_INTERNAL", + codeIncludes.empty() ? "{ No extra code files specified }" + : cmJoin(codeIncludes, "\n")); + + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Configure file: " << isScriptTemplate << " to " + << isScriptFile << std::endl); + + return ConfigureFile(isScriptTemplate, isScriptFile); +} + +bool cmCPackInnoSetupGenerator::Compile() +{ + const std::string& isScriptFile = + cmStrCat(GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/ISScript.iss"); + const std::string& isccLogFile = + cmStrCat(GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/ISCCOutput.log"); + + std::vector<std::string> isccArgs; + + // Custom defines + for (const std::string& i : GetOptions()) { + if (cmHasPrefix(i, "CPACK_INNOSETUP_DEFINE_")) { + const std::string& name = i.substr(cmStrLen("CPACK_INNOSETUP_DEFINE_")); + isccArgs.push_back( + cmStrCat("\"/D", name, '=', TranslateBool(GetOption(i)), '"')); + } + } + + if (IsSet("CPACK_INNOSETUP_EXECUTABLE_ARGUMENTS")) { + const cmList args(GetOption("CPACK_INNOSETUP_EXECUTABLE_ARGUMENTS")); + + isccArgs.insert(isccArgs.end(), args.begin(), args.end()); + } + + const std::string& isccCmd = + cmStrCat(QuotePath(GetOption("CPACK_INSTALLER_PROGRAM")), ' ', + cmJoin(isccArgs, " "), ' ', QuotePath(isScriptFile)); + + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << isccCmd << std::endl); + + std::string output; + int retVal = 1; + const bool res = cmSystemTools::RunSingleCommand( + isccCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose, + cmDuration::zero()); + + if (!res || retVal) { + cmGeneratedFileStream ofs(isccLogFile); + ofs << "# Run command: " << isccCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem running ISCC. Please check " + << isccLogFile << " for errors." << std::endl); + return false; + } + + return true; +} + +bool cmCPackInnoSetupGenerator::BuildDownloadedComponentArchive( + cmCPackComponent* component, const std::string& uploadDirectory, + std::string* hash) +{ + // Remove the old archive, if one exists + const std::string& archiveFile = + uploadDirectory + '/' + component->ArchiveFile; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Building downloaded component archive: " << archiveFile + << std::endl); + if (cmSystemTools::FileExists(archiveFile, true)) { + if (!cmSystemTools::RemoveFile(archiveFile)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Unable to remove archive file " << archiveFile + << std::endl); + return false; + } + } + + // Find a ZIP program + if (!IsSet("ZIP_EXECUTABLE")) { + ReadListFile("Internal/CPack/CPackZIP.cmake"); + + if (!IsSet("ZIP_EXECUTABLE")) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Unable to find ZIP program" << std::endl); + return false; + } + } + + if (!RequireOption("CPACK_TOPLEVEL_DIRECTORY") || + !RequireOption("CPACK_TEMPORARY_DIRECTORY") || + !RequireOption("CPACK_ZIP_NEED_QUOTES") || + !RequireOption("CPACK_ZIP_COMMAND")) { + return false; + } + + // The directory where this component's files reside + const std::string& dirName = + cmStrCat(GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component->Name); + + // Build the list of files to go into this archive + const std::string& zipListFileName = + cmStrCat(GetOption("CPACK_TEMPORARY_DIRECTORY"), "/winZip.filelist"); + const bool needQuotesInFile = cmIsOn(GetOption("CPACK_ZIP_NEED_QUOTES")); + { // the scope is needed for cmGeneratedFileStream + cmGeneratedFileStream out(zipListFileName); + for (const std::string& i : component->Files) { + out << (needQuotesInFile ? Quote(i) : i) << std::endl; + } + } + + // Build the archive in the upload area + std::string cmd = GetOption("CPACK_ZIP_COMMAND"); + cmsys::SystemTools::ReplaceString(cmd, "<ARCHIVE>", archiveFile.c_str()); + cmsys::SystemTools::ReplaceString(cmd, "<FILELIST>", + zipListFileName.c_str()); + std::string output; + int retVal = -1; + const bool res = cmSystemTools::RunSingleCommand( + cmd, &output, &output, &retVal, dirName.c_str(), this->GeneratorVerbose, + cmDuration::zero()); + if (!res || retVal) { + std::string tmpFile = + cmStrCat(GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/CompressZip.log"); + cmGeneratedFileStream ofs(tmpFile); + ofs << "# Run command: " << cmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem running zip command: " << cmd << std::endl + << "Please check " << tmpFile + << " for errors" + << std::endl); + return false; + } + + // Try to get the SHA256 hash of the archive file + if (hash == nullptr) { + return true; + } + +#ifdef _WIN32 + const std::string& hashCmd = + cmStrCat("certutil -hashfile ", QuotePath(archiveFile), " SHA256"); + + std::string hashOutput; + int hashRetVal = -1; + const bool hashRes = cmSystemTools::RunSingleCommand( + hashCmd, &hashOutput, &hashOutput, &hashRetVal, nullptr, + this->GeneratorVerbose, cmDuration::zero()); + if (!hashRes || hashRetVal) { + cmCPackLogger(cmCPackLog::LOG_WARNING, + "Problem running certutil command: " << hashCmd + << std::endl); + } + *hash = cmTrimWhitespace(cmTokenize(hashOutput, "\n").at(1)); + + if (hash->length() != 64) { + cmCPackLogger(cmCPackLog::LOG_WARNING, + "Problem parsing certutil output of command: " << hashCmd + << std::endl); + hash->clear(); + } +#endif + + return true; +} + +cmValue cmCPackInnoSetupGenerator::RequireOption(const std::string& key) +{ + cmValue value = GetOption(key); + + if (!value) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Required variable " << key << " not set" << std::endl); + } + + return value; +} + +std::string cmCPackInnoSetupGenerator::CustomComponentInstallDirectory( + const cmCPackComponent* component) +{ + cmValue outputDir = GetOption( + cmStrCat("CPACK_INNOSETUP_", component->Name, "_INSTALL_DIRECTORY")); + if (outputDir) { + std::string destDir = cmSystemTools::ConvertToWindowsOutputPath(outputDir); + cmStripSuffixIfExists(destDir, '\\'); + + /* + * Add a dir instruction for the custom directory + * (only once and not for Inno Setup constants ending with '}') + */ + static std::vector<std::string> customDirectories; + if (!cmHasSuffix(destDir, '}') && + std::find(customDirectories.begin(), customDirectories.end(), + component->Name) == customDirectories.end()) { + cmCPackInnoSetupKeyValuePairs params; + params["Name"] = QuotePath(destDir); + params["Components"] = + CreateRecursiveComponentPath(component->Group, component->Name); + + dirInstructions.push_back(ISKeyValueLine(params)); + customDirectories.push_back(component->Name); + } + return destDir; + } + + return "{app}"; +} + +std::string cmCPackInnoSetupGenerator::TranslateBool(const std::string& value) +{ + if (value.empty()) { + return value; + } + + SetOptionIfNotSet("CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT", "ON"); + if (GetOption("CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT").IsOn()) { + if (cmIsOn(value)) { + return "yes"; + } + if (cmIsOff(value)) { + return "no"; + } + } + + return value; +} + +std::string cmCPackInnoSetupGenerator::ISKeyValueLine( + const cmCPackInnoSetupKeyValuePairs& params) +{ + /* + * To simplify readability of the generated code, the keys are sorted. + * Unknown keys are ignored to avoid errors during compilation. + */ + static const char* const availableKeys[] = { + "Source", "DestDir", "Name", "Filename", + "Description", "GroupDescription", "MessagesFile", "Types", + "ExternalSize", "BeforeInstall", "Flags", "Components", + "Tasks" + }; + + std::vector<std::string> keys; + for (const char* i : availableKeys) { + if (params.count(i)) { + keys.push_back(cmStrCat(i, ": ", params.at(i))); + } + } + + return cmJoin(keys, "; "); +} + +std::string cmCPackInnoSetupGenerator::CreateRecursiveComponentPath( + cmCPackComponentGroup* group, const std::string& path) +{ + if (group == nullptr) { + return path; + } + + const std::string& newPath = + path.empty() ? group->Name : cmStrCat(group->Name, '\\', path); + return CreateRecursiveComponentPath(group->ParentGroup, newPath); +} + +void cmCPackInnoSetupGenerator::CreateRecursiveComponentGroups( + cmCPackComponentGroup* group) +{ + if (group == nullptr) { + return; + } + + CreateRecursiveComponentGroups(group->ParentGroup); + + static std::vector<cmCPackComponentGroup*> processedGroups; + if (std::find(processedGroups.begin(), processedGroups.end(), group) == + processedGroups.end()) { + processedGroups.push_back(group); + + cmCPackInnoSetupKeyValuePairs params; + + params["Name"] = Quote(CreateRecursiveComponentPath(group)); + params["Description"] = Quote(group->DisplayName); + + componentInstructions.push_back(ISKeyValueLine(params)); + } +} + +std::string cmCPackInnoSetupGenerator::Quote(const std::string& string) +{ + if (cmHasPrefix(string, '"') && cmHasSuffix(string, '"')) { + return Quote(string.substr(1, string.length() - 2)); + } + + // Double quote syntax + std::string nString = string; + cmSystemTools::ReplaceString(nString, "\"", "\"\""); + return cmStrCat('"', nString, '"'); +} + +std::string cmCPackInnoSetupGenerator::QuotePath(const std::string& path) +{ + return Quote(cmSystemTools::ConvertToWindowsOutputPath(path)); +} + +std::string cmCPackInnoSetupGenerator::PrepareForConstant( + const std::string& string) +{ + std::string nString = string; + + cmSystemTools::ReplaceString(nString, "%", "%25"); // First replacement! + cmSystemTools::ReplaceString(nString, "\"", "%22"); + cmSystemTools::ReplaceString(nString, ",", "%2c"); + cmSystemTools::ReplaceString(nString, "|", "%7c"); + cmSystemTools::ReplaceString(nString, "}", "%7d"); + + return nString; +} diff --git a/Source/CPack/cmCPackInnoSetupGenerator.h b/Source/CPack/cmCPackInnoSetupGenerator.h new file mode 100644 index 0000000000..342f227e00 --- /dev/null +++ b/Source/CPack/cmCPackInnoSetupGenerator.h @@ -0,0 +1,116 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying +file Copyright.txt or https://cmake.org/licensing for details. */ + +#pragma once + +#include <map> +#include <string> +#include <vector> + +#include "cmCPackGenerator.h" +#include "cmValue.h" + +using cmCPackInnoSetupKeyValuePairs = std::map<std::string, std::string>; + +class cmCPackComponentGroup; +class cmCPackComponent; + +/** \class cmCPackInnoSetupGenerator + * \brief A generator for Inno Setup + * + * https://jrsoftware.org/isinfo.php + */ +class cmCPackInnoSetupGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackInnoSetupGenerator, cmCPackGenerator); + + /** + * Construct generator + */ + cmCPackInnoSetupGenerator(); + ~cmCPackInnoSetupGenerator() override; + + static bool CanGenerate(); + +protected: + int InitializeInternal() override; + int PackageFiles() override; + + inline const char* GetOutputExtension() override { return ".exe"; } + + inline cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() + const override + { + return cmCPackGenerator::SETDESTDIR_UNSUPPORTED; + } + + inline bool SupportsAbsoluteDestination() const override { return false; } + inline bool SupportsComponentInstallation() const override { return true; } + +private: + bool ProcessSetupSection(); + bool ProcessFiles(); + bool ProcessComponents(); + + bool ConfigureISScript(); + bool Compile(); + + bool BuildDownloadedComponentArchive(cmCPackComponent* component, + const std::string& uploadDirectory, + std::string* hash); + + /** + * Returns the option's value or an empty string if the option isn't set. + */ + cmValue RequireOption(const std::string& key); + + std::string CustomComponentInstallDirectory( + const cmCPackComponent* component); + + /** + * Translates boolean expressions into "yes" or "no", as required in + * Inno Setup (only if "CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT" is on). + */ + std::string TranslateBool(const std::string& value); + + /** + * Creates a typical line of key and value pairs using the given map. + * + * (e.g.: Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; + * GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked) + */ + std::string ISKeyValueLine(const cmCPackInnoSetupKeyValuePairs& params); + + std::string CreateRecursiveComponentPath(cmCPackComponentGroup* group, + const std::string& path = ""); + + void CreateRecursiveComponentGroups(cmCPackComponentGroup* group); + + /** + * These functions add quotes if the given value hasn't already quotes. + * Paths are converted into the format used by Windows before. + */ + std::string Quote(const std::string& string); + std::string QuotePath(const std::string& path); + + /** + * This function replaces the following 5 characters with their %-encoding: + * '|' '}' ',' '%' '"' + * Required for Inno Setup constants like {cm:...} + */ + std::string PrepareForConstant(const std::string& string); + + std::vector<std::string> includeDirectives; + cmCPackInnoSetupKeyValuePairs setupDirectives; + bool toplevelProgramFolder; + std::vector<std::string> languageInstructions; + std::vector<std::string> fileInstructions; + std::vector<std::string> dirInstructions; + std::vector<std::string> typeInstructions; + std::vector<std::string> componentInstructions; + std::vector<std::string> iconInstructions; + std::vector<std::string> desktopIconComponents; + std::vector<std::string> runInstructions; + std::vector<std::string> codeIncludes; +}; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index d7119c5223..7749b29303 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -19,6 +19,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -245,8 +246,7 @@ int cmCPackNSISGenerator::PackageFiles() std::string nsisPreArguments; if (cmValue nsisArguments = this->GetOption("CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS")) { - std::vector<std::string> expandedArguments; - cmExpandList(nsisArguments, expandedArguments); + cmList expandedArguments{ nsisArguments }; for (auto& arg : expandedArguments) { if (!cmHasPrefix(arg, NSIS_OPT)) { @@ -259,8 +259,7 @@ int cmCPackNSISGenerator::PackageFiles() std::string nsisPostArguments; if (cmValue nsisArguments = this->GetOption("CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS")) { - std::vector<std::string> expandedArguments; - cmExpandList(nsisArguments, expandedArguments); + cmList expandedArguments{ nsisArguments }; for (auto& arg : expandedArguments) { if (!cmHasPrefix(arg, NSIS_OPT)) { nsisPostArguments = cmStrCat(nsisPostArguments, NSIS_OPT); @@ -545,14 +544,14 @@ int cmCPackNSISGenerator::InitializeInternal() this->GetOption("CPACK_CREATE_DESKTOP_LINKS"); cmValue cpackNsisExecutablesDirectory = this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"); - std::vector<std::string> cpackPackageDesktopLinksVector; + cmList cpackPackageDesktopLinksList; if (cpackPackageDeskTopLinks) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: " << cpackPackageDeskTopLinks << std::endl); - cmExpandList(cpackPackageDeskTopLinks, cpackPackageDesktopLinksVector); - for (std::string const& cpdl : cpackPackageDesktopLinksVector) { + cpackPackageDesktopLinksList.assign(cpackPackageDeskTopLinks); + for (std::string const& cpdl : cpackPackageDesktopLinksList) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: " << cpdl << std::endl); } @@ -569,9 +568,8 @@ int cmCPackNSISGenerator::InitializeInternal() cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: " << cpackPackageExecutables << "." << std::endl); - std::vector<std::string> cpackPackageExecutablesVector = - cmExpandedList(cpackPackageExecutables); - if (cpackPackageExecutablesVector.size() % 2 != 0) { + cmList cpackPackageExecutablesList{ cpackPackageExecutables }; + if (cpackPackageExecutablesList.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and " @@ -579,9 +577,9 @@ int cmCPackNSISGenerator::InitializeInternal() << std::endl); return 0; } - std::vector<std::string>::iterator it; - for (it = cpackPackageExecutablesVector.begin(); - it != cpackPackageExecutablesVector.end(); ++it) { + cmList::iterator it; + for (it = cpackPackageExecutablesList.begin(); + it != cpackPackageExecutablesList.end(); ++it) { std::string execName = *it; ++it; std::string linkName = *it; @@ -592,7 +590,7 @@ int cmCPackNSISGenerator::InitializeInternal() << ".lnk\"" << std::endl; // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on // if so add a desktop link - if (cm::contains(cpackPackageDesktopLinksVector, execName)) { + if (cm::contains(cpackPackageDesktopLinksList, execName)) { str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n"; str << " CreateShortCut \"$DESKTOP\\" << linkName << R"(.lnk" "$INSTDIR\)" << cpackNsisExecutablesDirectory << "\\" @@ -622,9 +620,8 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, } cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackMenuLinks: " << cpackMenuLinks << "." << std::endl); - std::vector<std::string> cpackMenuLinksVector = - cmExpandedList(cpackMenuLinks); - if (cpackMenuLinksVector.size() % 2 != 0) { + cmList cpackMenuLinksList{ cpackMenuLinks }; + if (cpackMenuLinksList.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, "CPACK_NSIS_MENU_LINKS should contain pairs of <shortcut target> and " @@ -636,9 +633,8 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, static cmsys::RegularExpression urlRegex( "^(mailto:|(ftps?|https?|news)://).*$"); - std::vector<std::string>::iterator it; - for (it = cpackMenuLinksVector.begin(); it != cpackMenuLinksVector.end(); - ++it) { + cmList::iterator it; + for (it = cpackMenuLinksList.begin(); it != cpackMenuLinksList.end(); ++it) { std::string sourceName = *it; const bool url = urlRegex.find(sourceName); diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 234bc59352..90716e6e0d 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -29,6 +29,7 @@ #include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmJSONState.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" @@ -509,8 +510,8 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified\n"); } else { - std::vector<std::string> generatorsVector = cmExpandedList(*genList); - for (std::string const& gen : generatorsVector) { + cmList generatorsList{ *genList }; + for (std::string const& gen : generatorsList) { cmMakefile::ScopePushPop raii(&globalMF); cmMakefile* mf = &globalMF; cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index c6387ab353..882b579fff 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -17,6 +17,7 @@ #include "cmDuration.h" #include "cmFileTimeCache.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmProcessOutput.h" #include "cmStringAlgorithms.h" diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index 1f3633de5b..bae1f54011 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -4,13 +4,13 @@ #include <cstring> #include <sstream> -#include <vector> #include <cmext/string_view> #include "cmCTest.h" #include "cmCTestConfigureHandler.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -25,10 +25,10 @@ void cmCTestConfigureCommand::BindArguments() cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() { - std::vector<std::string> options; + cmList options; if (!this->Options.empty()) { - cmExpandList(this->Options, options); + options.assign(this->Options); } if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) { diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index b2fb069fd5..a6e7ac52c8 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -14,6 +14,7 @@ #include "cmCTest.h" #include "cmCTestVC.h" +#include "cmList.h" #include "cmProcessOutput.h" #include "cmProcessTools.h" #include "cmStringAlgorithms.h" @@ -215,7 +216,7 @@ bool cmCTestGIT::UpdateByFetchAndReset() bool cmCTestGIT::UpdateByCustom(std::string const& custom) { - std::vector<std::string> git_custom_command = cmExpandedList(custom, true); + cmList git_custom_command{ custom, cmList::EmptyElements::Yes }; std::vector<char const*> git_custom; git_custom.reserve(git_custom_command.size() + 1); for (std::string const& i : git_custom_command) { diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 0e67c4122e..e22ec4b556 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -13,9 +13,9 @@ #include "cmCTest.h" #include "cmCTestVC.h" +#include "cmList.h" #include "cmProcessTools.h" #include "cmRange.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmCTestP4::cmCTestP4(cmCTest* ct, std::ostream& log) @@ -460,7 +460,7 @@ bool cmCTestP4::LoadModifications() bool cmCTestP4::UpdateCustom(const std::string& custom) { - std::vector<std::string> p4_custom_command = cmExpandedList(custom, true); + cmList p4_custom_command{ custom, cmList::EmptyElements::Yes }; std::vector<char const*> p4_custom; p4_custom.reserve(p4_custom_command.size() + 1); diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index ee06b29c67..461ad1a947 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -33,6 +33,7 @@ #include "cmDuration.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -521,7 +522,7 @@ int cmCTestScriptHandler::RunCurrentScript() // set any environment variables if (!this->CTestEnv.empty()) { - std::vector<std::string> envArgs = cmExpandedList(this->CTestEnv); + cmList envArgs{ this->CTestEnv }; cmSystemTools::AppendEnv(envArgs); } @@ -625,7 +626,7 @@ int cmCTestScriptHandler::PerformExtraUpdates() // do an initial cvs update as required command = this->UpdateCmd; for (std::string const& eu : this->ExtraUpdates) { - std::vector<std::string> cvsArgs = cmExpandedList(eu); + cmList cvsArgs{ eu }; if (cvsArgs.size() == 2) { std::string fullCommand = cmStrCat(command, " update ", cvsArgs[1]); output.clear(); @@ -764,7 +765,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() } // run ctest, it may be more than one command in here - std::vector<std::string> ctestCommands = cmExpandedList(this->CTestCmd); + cmList ctestCommands{ this->CTestCmd }; // for each variable/argument do a putenv for (std::string const& ctestCommand : ctestCommands) { command = ctestCommand; diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index a1933cccb1..a92f9f28ec 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -13,10 +13,10 @@ #include "cmCTest.h" #include "cmCTestSubmitHandler.h" #include "cmCommand.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -64,14 +64,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() cmValue notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); if (notesFilesVariable) { - std::vector<std::string> notesFiles = cmExpandedList(*notesFilesVariable); + cmList notesFiles{ *notesFilesVariable }; this->CTest->GenerateNotesFile(notesFiles); } cmValue extraFilesVariable = this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES"); if (extraFilesVariable) { - std::vector<std::string> extraFiles = cmExpandedList(*extraFilesVariable); + cmList extraFiles{ *extraFilesVariable }; if (!this->CTest->SubmitExtraFiles(extraFiles)) { this->SetError("problem submitting extra files."); return nullptr; diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 3ff8c8f280..a095e5dc63 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -22,6 +22,7 @@ #include "cmCurl.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -160,7 +161,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); - std::vector<std::string> args = cmExpandedList(curlopt); + cmList args{ curlopt }; bool verifyPeerOff = false; bool verifyHostOff = false; for (std::string const& arg : args) { @@ -499,7 +500,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, cmCTestCurl curl(this->CTest); curl.SetQuiet(this->Quiet); std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); - std::vector<std::string> args = cmExpandedList(curlopt); + cmList args{ curlopt }; curl.SetCurlOptions(args); auto submitInactivityTimeout = this->GetSubmitInactivityTimeout(); if (submitInactivityTimeout != 0) { diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index f693ace4b5..3a1cb64708 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -38,6 +38,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmJSONState.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" @@ -2203,9 +2204,8 @@ bool cmCTestTestHandler::SetTestsProperties( for (cmCTestTestProperties& rt : this->TestList) { if (t == rt.Name) { if (key == "_BACKTRACE_TRIPLES"_s) { - std::vector<std::string> triples; // allow empty args in the triples - cmExpandList(val, triples, true); + cmList triples{ val, cmList::EmptyElements::Yes }; // Ensure we have complete triples otherwise the data is corrupt. if (triples.size() % 3 == 0) { @@ -2214,7 +2214,7 @@ bool cmCTestTestHandler::SetTestsProperties( // the first entry represents the top of the trace so we need to // reconstruct the backtrace in reverse - for (size_t i = triples.size(); i >= 3; i -= 3) { + for (auto i = triples.size(); i >= 3; i -= 3) { cmListFileContext fc; fc.FilePath = triples[i - 3]; long line = 0; @@ -2235,19 +2235,19 @@ bool cmCTestTestHandler::SetTestsProperties( } else if (key == "ATTACHED_FILES_ON_FAIL"_s) { cmExpandList(val, rt.AttachOnFail); } else if (key == "RESOURCE_LOCK"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; rt.LockedResources.insert(lval.begin(), lval.end()); } else if (key == "FIXTURES_SETUP"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; rt.FixturesSetup.insert(lval.begin(), lval.end()); } else if (key == "FIXTURES_CLEANUP"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; rt.FixturesCleanup.insert(lval.begin(), lval.end()); } else if (key == "FIXTURES_REQUIRED"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; rt.FixturesRequired.insert(lval.begin(), lval.end()); } else if (key == "TIMEOUT"_s) { @@ -2260,12 +2260,12 @@ bool cmCTestTestHandler::SetTestsProperties( } else if (key == "RUN_SERIAL"_s) { rt.RunSerial = cmIsOn(val); } else if (key == "FAIL_REGULAR_EXPRESSION"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; for (std::string const& cr : lval) { rt.ErrorRegularExpressions.emplace_back(cr, cr); } } else if (key == "SKIP_REGULAR_EXPRESSION"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; for (std::string const& cr : lval) { rt.SkipRegularExpressions.emplace_back(cr, cr); } @@ -2292,7 +2292,7 @@ bool cmCTestTestHandler::SetTestsProperties( } else if (key == "ENVIRONMENT_MODIFICATION"_s) { cmExpandList(val, rt.EnvironmentModification); } else if (key == "LABELS"_s) { - std::vector<std::string> Labels = cmExpandedList(val); + cmList Labels{ val }; rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end()); // sort the array std::sort(rt.Labels.begin(), rt.Labels.end()); @@ -2309,21 +2309,21 @@ bool cmCTestTestHandler::SetTestsProperties( rt.Measurements[val] = "1"; } } else if (key == "PASS_REGULAR_EXPRESSION"_s) { - std::vector<std::string> lval = cmExpandedList(val); + cmList lval{ val }; for (std::string const& cr : lval) { rt.RequiredRegularExpressions.emplace_back(cr, cr); } } else if (key == "WORKING_DIRECTORY"_s) { rt.Directory = val; } else if (key == "TIMEOUT_AFTER_MATCH"_s) { - std::vector<std::string> propArgs = cmExpandedList(val); + cmList propArgs{ val }; if (propArgs.size() != 2) { cmCTestLog(this->CTest, WARNING, "TIMEOUT_AFTER_MATCH expects two arguments, found " << propArgs.size() << std::endl); } else { rt.AlternateTimeout = cmDuration(atof(propArgs[0].c_str())); - std::vector<std::string> lval = cmExpandedList(propArgs[1]); + cmList lval{ propArgs[1] }; for (std::string const& cr : lval) { rt.TimeoutRegularExpressions.emplace_back(cr, cr); } @@ -2365,7 +2365,7 @@ bool cmCTestTestHandler::SetDirectoryProperties( std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); if (cwd == rt.Directory) { if (key == "LABELS"_s) { - std::vector<std::string> DirectoryLabels = cmExpandedList(val); + cmList DirectoryLabels{ val }; rt.Labels.insert(rt.Labels.end(), DirectoryLabels.begin(), DirectoryLabels.end()); diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx index e9ec09ee28..fc5450ef2b 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx @@ -4,7 +4,6 @@ #include <cassert> #include <utility> -#include <vector> #include <cm/memory> @@ -15,9 +14,9 @@ #include "cmCursesPathWidget.h" #include "cmCursesStringWidget.h" #include "cmCursesWidget.h" +#include "cmList.h" #include "cmState.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -76,7 +75,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( if (stringsProp) { auto ow = cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1); - for (std::string const& opt : cmExpandedList(*stringsProp)) { + for (auto const& opt : cmList{ *stringsProp }) { ow->AddOption(opt); } ow->SetOption(*value); diff --git a/Source/Modules/CMakeBuildUtilities.cmake b/Source/Modules/CMakeBuildUtilities.cmake index 3dc099f7c8..d6e3e884dc 100644 --- a/Source/Modules/CMakeBuildUtilities.cmake +++ b/Source/Modules/CMakeBuildUtilities.cmake @@ -279,7 +279,7 @@ else() set(ENABLE_LIBXML2 OFF) set(ENABLE_EXPAT OFF) set(ENABLE_PCREPOSIX OFF) - set(ENABLE_LibGCC OFF) + set(ENABLE_LIBGCC OFF) set(ENABLE_CNG OFF) set(ENABLE_TAR OFF) set(ENABLE_TAR_SHARED OFF) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 58129a06b6..8bfd7c87c7 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -21,10 +21,12 @@ #include "cmArgumentParser.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmWindowsRegistry.h" #ifdef _WIN32 @@ -303,7 +305,8 @@ std::map<std::string, std::string> GetOSReleaseVariables( } // 2. User provided (append to the CMake prvided) - makefile.GetDefExpandList("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS", scripts); + cmList::append( + scripts, makefile.GetDefinition("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS")); // Filter out files that are not in format `NNN-name.cmake` auto checkName = [](std::string const& filepath) -> bool { @@ -330,11 +333,11 @@ std::map<std::string, std::string> GetOSReleaseVariables( }); // Name of the variable to put the results - auto const result_variable = "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT"_s; + std::string const result_variable{ "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT" }; for (auto const& script : scripts) { // Unset the result variable - makefile.RemoveDefinition(result_variable.data()); + makefile.RemoveDefinition(result_variable); // include FATAL_ERROR and ERROR in the return status if (!makefile.ReadListFile(script) || @@ -343,8 +346,8 @@ std::map<std::string, std::string> GetOSReleaseVariables( continue; } - std::vector<std::string> variables; - if (!makefile.GetDefExpandList(result_variable.data(), variables)) { + cmList variables{ makefile.GetDefinition(result_variable) }; + if (variables.empty()) { // Heh, this script didn't found anything... go try the next one. continue; } @@ -370,7 +373,7 @@ std::map<std::string, std::string> GetOSReleaseVariables( } } - makefile.RemoveDefinition(result_variable.data()); + makefile.RemoveDefinition(result_variable); return data; } diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx index 7755082236..0c8f53781a 100644 --- a/Source/cmCMakePathCommand.cxx +++ b/Source/cmCMakePathCommand.cxx @@ -18,6 +18,7 @@ #include "cmArgumentParserTypes.h" #include "cmCMakePath.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmStringAlgorithms.h" @@ -626,12 +627,12 @@ bool HandleConvertCommand(std::vector<std::string> const& args, return false; } - std::vector<std::string> paths; + cmList paths; if (action == cmakePath) { paths = cmSystemTools::SplitString(args[1], pathSep.front()); } else { - cmExpandList(args[1], paths); + paths.assign(args[1]); } for (auto& path : paths) { @@ -648,7 +649,7 @@ bool HandleConvertCommand(std::vector<std::string> const& args, } } - auto value = cmJoin(paths, action == cmakePath ? ";"_s : pathSep); + auto value = action == cmakePath ? paths.to_string() : paths.join(pathSep); status.GetMakefile().AddDefinition(args[3], value); return true; diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index 13e8bad1f1..13eddbe24f 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx @@ -4,7 +4,6 @@ #include <algorithm> #include <cassert> -#include <cstdlib> #include <functional> #include <iostream> #include <iterator> @@ -49,6 +48,7 @@ template <typename T> using PresetPair = cmCMakePresetsGraph::PresetPair<T>; using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult; using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander; +using cmCMakePresetsGraphInternal::ExpandMacros; void InheritString(std::string& child, const std::string& parent) { @@ -204,14 +204,6 @@ bool IsValidMacroNamespace(const std::string& str) ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, const std::vector<MacroExpander>& macroExpanders, int version); -ExpandMacroResult ExpandMacros( - std::string& out, const std::vector<MacroExpander>& macroExpanders, - int version); -ExpandMacroResult ExpandMacro(std::string& out, - const std::string& macroNamespace, - const std::string& macroName, - const std::vector<MacroExpander>& macroExpanders, - int version); bool ExpandMacros(const cmCMakePresetsGraph& graph, const ConfigurePreset& preset, @@ -448,9 +440,9 @@ bool ExpandMacros(cmCMakePresetsGraph& graph, const T& preset, if (macroName.empty()) { return ExpandMacroResult::Error; } - const char* value = std::getenv(macroName.c_str()); - if (value) { - result += value; + if (cm::optional<std::string> value = + cmSystemTools::GetEnvVar(macroName)) { + result += *value; } return ExpandMacroResult::Ok; } @@ -515,8 +507,9 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, status = CycleStatus::Verified; return ExpandMacroResult::Ok; } +} -ExpandMacroResult ExpandMacros( +ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros( std::string& out, const std::vector<MacroExpander>& macroExpanders, int version) { @@ -595,11 +588,10 @@ ExpandMacroResult ExpandMacros( return ExpandMacroResult::Ok; } -ExpandMacroResult ExpandMacro(std::string& out, - const std::string& macroNamespace, - const std::string& macroName, - const std::vector<MacroExpander>& macroExpanders, - int version) +ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacro( + std::string& out, const std::string& macroNamespace, + const std::string& macroName, + const std::vector<MacroExpander>& macroExpanders, int version) { for (auto const& macroExpander : macroExpanders) { auto result = macroExpander(macroNamespace, macroName, out, version); @@ -615,6 +607,7 @@ ExpandMacroResult ExpandMacro(std::string& out, return ExpandMacroResult::Error; } +namespace { template <typename T> bool SetupWorkflowConfigurePreset(const T& preset, const ConfigurePreset*& configurePreset, diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h index db784c341a..f133efb124 100644 --- a/Source/cmCMakePresetsGraphInternal.h +++ b/Source/cmCMakePresetsGraphInternal.h @@ -28,6 +28,16 @@ enum class ExpandMacroResult using MacroExpander = std::function<ExpandMacroResult( const std::string&, const std::string&, std::string&, int version)>; + +ExpandMacroResult ExpandMacros( + std::string& out, const std::vector<MacroExpander>& macroExpanders, + int version); + +ExpandMacroResult ExpandMacro(std::string& out, + const std::string& macroNamespace, + const std::string& macroName, + const std::vector<MacroExpander>& macroExpanders, + int version); } class cmCMakePresetsGraph::Condition diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index bc829f3e44..54fea409c4 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -33,6 +33,9 @@ using PackagePreset = cmCMakePresetsGraph::PackagePreset; using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset; using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; using JSONHelperBuilder = cmJSONHelperBuilder; +using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult; +using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander; +using cmCMakePresetsGraphInternal::ExpandMacros; constexpr int MIN_VERSION = 1; constexpr int MAX_VERSION = 7; @@ -688,7 +691,39 @@ bool cmCMakePresetsGraph::ReadJSONFile(const std::string& filename, return true; }; - for (auto include : presets.Include) { + std::vector<MacroExpander> macroExpanders; + + MacroExpander environmentMacroExpander = + [](const std::string& macroNamespace, const std::string& macroName, + std::string& expanded, int /*version*/) -> ExpandMacroResult { + if (macroNamespace == "penv") { + if (macroName.empty()) { + return ExpandMacroResult::Error; + } + if (cm::optional<std::string> value = + cmSystemTools::GetEnvVar(macroName)) { + expanded += *value; + } + return ExpandMacroResult::Ok; + } + + return ExpandMacroResult::Ignore; + }; + + macroExpanders.push_back(environmentMacroExpander); + + for (Json::ArrayIndex i = 0; i < presets.Include.size(); ++i) { + auto include = presets.Include[i]; + + // Support for macro expansion in includes added in version 7 + if (v >= 7) { + if (ExpandMacros(include, macroExpanders, v) != ExpandMacroResult::Ok) { + cmCMakePresetErrors::INVALID_INCLUDE(&root["include"][i], + &this->parseState); + return false; + } + } + if (!cmSystemTools::FileIsFullPath(include)) { auto directory = cmSystemTools::GetFilenamePath(filename); include = cmStrCat(directory, '/', include); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index c8eea38b75..a3110413f8 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -55,6 +55,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmJSONState.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmProcessOutput.h" #include "cmState.h" @@ -1468,7 +1469,7 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml) ch->GetCMake()->GetState()->GetGlobalProperty("SubProjectLabels"); if (labels) { xml.StartElement("Labels"); - std::vector<std::string> args = cmExpandedList(*labels); + cmList args{ *labels }; for (std::string const& i : args) { xml.Element("Label", i); } @@ -1500,7 +1501,7 @@ std::vector<std::string> cmCTest::GetLabelsForSubprojects() { std::string labelsForSubprojects = this->GetCTestConfiguration("LabelsForSubprojects"); - std::vector<std::string> subprojects = cmExpandedList(labelsForSubprojects); + cmList subprojects{ labelsForSubprojects }; // sort the array std::sort(subprojects.begin(), subprojects.end()); @@ -1508,7 +1509,7 @@ std::vector<std::string> cmCTest::GetLabelsForSubprojects() auto new_end = std::unique(subprojects.begin(), subprojects.end()); subprojects.erase(new_end, subprojects.end()); - return subprojects; + return std::move(subprojects.data()); } void cmCTest::EndXML(cmXMLWriter& xml) @@ -3098,8 +3099,7 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def, } cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl); - vec.clear(); - cmExpandList(*dval, vec); + cmList::assign(vec, *dval); for (std::string const& it : vec) { cmCTestLog(this, DEBUG, " -- " << it << std::endl); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index b9d1f66d2a..d95dcc44ce 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -12,6 +12,7 @@ #include "cmsys/Glob.hxx" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmMessageType.h" #include "cmMessenger.h" #include "cmState.h" @@ -531,15 +532,11 @@ void cmCacheManager::AddCacheEntry(const std::string& key, cmValue value, // make sure we only use unix style paths if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) { if (e.Value.find(';') != std::string::npos) { - std::vector<std::string> paths = cmExpandedList(e.Value); - const char* sep = ""; - e.Value = ""; + cmList paths{ e.Value }; for (std::string& i : paths) { cmSystemTools::ConvertToUnixSlashes(i); - e.Value += sep; - e.Value += i; - sep = ";"; } + e.Value = paths.to_string(); } else { cmSystemTools::ConvertToUnixSlashes(e.Value); } diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index f6fdd48969..1cb62b39d8 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -15,6 +15,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalCommonGenerator.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalCommonGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -303,8 +304,7 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher( *launcherProp, this->LocalCommonGenerator, config, this->GeneratorTarget, &dagChecker, this->GeneratorTarget, lang); // Convert ;-delimited list to single string - std::vector<std::string> args = - cmExpandedList(evaluatedLinklauncher, true); + cmList args{ evaluatedLinklauncher, cmList::EmptyElements::Yes }; if (!args.empty()) { args[0] = this->LocalCommonGenerator->ConvertToOutputFormat( args[0], cmOutputConverter::SHELL); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 5f408d0c65..f51a1c895c 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -20,6 +20,7 @@ #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -627,7 +628,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(size_t depender_index, // This is called to add the dependencies named by // <item>_LIB_DEPENDS. The variable contains a semicolon-separated // list. The list contains link-type;item pairs and just items. - std::vector<std::string> deplist = cmExpandedList(value); + cmList deplist{ value }; // Look for entries meant for this configuration. std::vector<cmLinkItem> actual_libs; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index a93477b924..5d44a6ae70 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -15,6 +15,7 @@ #include "cmComputeLinkDepends.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -858,8 +859,8 @@ bool cmComputeLinkInformation::AddLibraryFeature(std::string const& feature) return false; } - auto items = cmExpandListWithBacktrace(*langFeature, - this->Target->GetBacktrace(), true); + auto items = cmExpandListWithBacktrace( + *langFeature, this->Target->GetBacktrace(), cmList::EmptyElements::Yes); if ((items.size() == 1 && !IsValidFeatureFormat(items.front().Value)) || (items.size() == 3 && !IsValidFeatureFormat(items[1].Value))) { @@ -1016,8 +1017,8 @@ cmComputeLinkInformation::GetGroupFeature(std::string const& feature) .first->second; } - auto items = cmExpandListWithBacktrace(*langFeature, - this->Target->GetBacktrace(), true); + auto items = cmExpandListWithBacktrace( + *langFeature, this->Target->GetBacktrace(), cmList::EmptyElements::Yes); // replace LINKER: pattern this->Target->ResolveLinkerWrapper(items, this->LinkLanguage, true); @@ -1072,8 +1073,8 @@ void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang) } if (cmValue runtimeLinkOptions = this->Makefile->GetDefinition(cmStrCat( "CMAKE_", lang, "_RUNTIME_LIBRARY_LINK_OPTIONS_", runtimeLibrary))) { - std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions); - for (std::string const& i : libsVec) { + cmList libs{ *runtimeLinkOptions }; + for (auto const& i : libs) { if (!cm::contains(this->ImplicitLinkLibs, i)) { this->AddItem({ i }); } @@ -1087,8 +1088,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // linker language. std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES"); if (cmValue libs = this->Makefile->GetDefinition(libVar)) { - std::vector<std::string> libsVec = cmExpandedList(*libs); - for (std::string const& i : libsVec) { + cmList libsList{ *libs }; + for (auto const& i : libsList) { if (!cm::contains(this->ImplicitLinkLibs, i)) { this->AddItem({ i }); } @@ -1099,8 +1100,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // implied by the linker language. std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES"); if (cmValue dirs = this->Makefile->GetDefinition(dirVar)) { - std::vector<std::string> dirsVec = cmExpandedList(*dirs); - this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec); + cmList dirsList{ *dirs }; + this->OrderLinkerSearchPath->AddLanguageDirectories(dirsList); } } @@ -1370,15 +1371,15 @@ void cmComputeLinkInformation::ComputeItemParserInfo() LinkUnknown); if (cmValue linkSuffixes = mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) { - std::vector<std::string> linkSuffixVec = cmExpandedList(*linkSuffixes); - for (std::string const& i : linkSuffixVec) { + cmList linkSuffixList{ *linkSuffixes }; + for (auto const& i : linkSuffixList) { this->AddLinkExtension(i, LinkUnknown); } } if (cmValue sharedSuffixes = mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) { - std::vector<std::string> sharedSuffixVec = cmExpandedList(*sharedSuffixes); - for (std::string const& i : sharedSuffixVec) { + cmList sharedSuffixList{ *sharedSuffixes }; + for (std::string const& i : sharedSuffixList) { this->AddLinkExtension(i, LinkShared); } } @@ -1916,19 +1917,18 @@ void cmComputeLinkInformation::DropDirectoryItem(BT<std::string> const& item) void cmComputeLinkInformation::ComputeFrameworkInfo() { // Avoid adding implicit framework paths. - std::vector<std::string> implicitDirVec; + cmList implicitDirs; // Get platform-wide implicit directories. - this->Makefile->GetDefExpandList( - "CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", implicitDirVec); + implicitDirs.assign(this->Makefile->GetDefinition( + "CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")); // Get language-specific implicit directories. std::string implicitDirVar = cmStrCat( "CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"); - this->Makefile->GetDefExpandList(implicitDirVar, implicitDirVec); + implicitDirs.append(this->Makefile->GetDefinition(implicitDirVar)); - this->FrameworkPathsEmitted.insert(implicitDirVec.begin(), - implicitDirVec.end()); + this->FrameworkPathsEmitted.insert(implicitDirs.begin(), implicitDirs.end()); } void cmComputeLinkInformation::AddFrameworkPath(std::string const& p) @@ -2138,17 +2138,15 @@ void cmComputeLinkInformation::PrintLinkPolicyDiagnosis(std::ostream& os) void cmComputeLinkInformation::LoadImplicitLinkInfo() { - std::vector<std::string> implicitDirVec; - // Get platform-wide implicit directories. - this->Makefile->GetDefExpandList("CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES", - implicitDirVec); + cmList implicitDirs{ this->Makefile->GetDefinition( + "CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES") }; // Append library architecture to all implicit platform directories // and add them to the set if (cmValue libraryArch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { - for (std::string const& i : implicitDirVec) { + for (auto const& i : implicitDirs) { this->ImplicitLinkDirs.insert(cmStrCat(i, '/', *libraryArch)); } } @@ -2156,19 +2154,18 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() // Get language-specific implicit directories. std::string implicitDirVar = cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_DIRECTORIES"); - this->Makefile->GetDefExpandList(implicitDirVar, implicitDirVec); + implicitDirs.append(this->Makefile->GetDefinition(implicitDirVar)); // Store implicit link directories. - this->ImplicitLinkDirs.insert(implicitDirVec.begin(), implicitDirVec.end()); + this->ImplicitLinkDirs.insert(implicitDirs.begin(), implicitDirs.end()); // Get language-specific implicit libraries. - std::vector<std::string> implicitLibVec; std::string implicitLibVar = cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_LIBRARIES"); - this->Makefile->GetDefExpandList(implicitLibVar, implicitLibVec); + cmList implicitLibs{ this->Makefile->GetDefinition(implicitLibVar) }; // Store implicit link libraries. - for (std::string const& item : implicitLibVec) { + for (auto const& item : implicitLibs) { // Items starting in '-' but not '-l' are flags, not libraries, // and should not be filtered by this implicit list. if (item[0] != '-' || item[1] == 'l') { @@ -2177,8 +2174,8 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() } // Get platform specific rpath link directories - this->Makefile->GetDefExpandList("CMAKE_PLATFORM_RUNTIME_PATH", - this->RuntimeLinkDirs); + cmList::append(this->RuntimeLinkDirs, + this->Makefile->GetDefinition("CMAKE_PLATFORM_RUNTIME_PATH")); } std::vector<std::string> const& @@ -2279,7 +2276,7 @@ static void cmCLI_ExpandListUnique(std::string const& str, std::vector<std::string>& out, std::set<std::string>& emitted) { - std::vector<std::string> tmp = cmExpandedList(str); + cmList tmp{ str }; for (std::string const& i : tmp) { if (emitted.insert(i).second) { out.push_back(i); diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 5de012a7fa..288e107d0a 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -18,6 +18,7 @@ #include "cmCMakePath.h" #include "cmExpandedCommandArgument.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" @@ -764,7 +765,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, cmValue rhs = this->Makefile.GetDefinition(args.nextnext->GetValue()); newArgs.ReduceTwoArgs( - rhs && cm::contains(cmExpandedList(*rhs, true), *lhs), args); + rhs && + cm::contains(cmList{ *rhs, cmList::EmptyElements::Yes }, *lhs), + args); } else if (this->Policy57Status == cmPolicies::WARN) { diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 3149ccfa9c..7d4ab50967 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -20,6 +20,7 @@ #include "cmConfigureLog.h" #include "cmExportTryCompileFileGenerator.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOutputConverter.h" @@ -125,7 +126,7 @@ ArgumentParser::Continue TryCompileLangProp(Arguments& args, ArgumentParser::Continue TryCompileCompileDefs(Arguments& args, cm::string_view val) { - cmExpandList(val, args.CompileDefs); + args.CompileDefs.append(val); return ArgumentParser::Continue::Yes; } @@ -788,7 +789,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode( if (!arguments.CompileDefs.empty()) { // Pass using bracket arguments to preserve content. fprintf(fout, "add_definitions([==[%s]==])\n", - cmJoin(arguments.CompileDefs, "]==] [==[").c_str()); + arguments.CompileDefs.join("]==] [==[").c_str()); } if (!targets.empty()) { @@ -1024,7 +1025,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode( if (cmValue varListStr = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { - std::vector<std::string> varList = cmExpandedList(*varListStr); + cmList varList{ *varListStr }; vars.insert(varList.begin(), varList.end()); } diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index ba38c196b8..c185c68feb 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -12,6 +12,7 @@ #include "cmArgumentParser.h" #include "cmArgumentParserTypes.h" +#include "cmList.h" #include "cmStateTypes.h" class cmConfigureLog; @@ -65,7 +66,7 @@ public: ArgumentParser::MaybeEmpty<std::vector<std::string>> CMakeFlags{ 1, "CMAKE_FLAGS" }; // fake argv[0] - std::vector<std::string> CompileDefs; + cmList CompileDefs; cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> LinkLibraries; ArgumentParser::MaybeEmpty<std::vector<std::string>> LinkOptions; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 14c22e3a45..7623ccfd18 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" @@ -116,7 +117,7 @@ std::vector<std::string> EvaluateDepends(std::vector<std::string> const& paths, /*outputConfig=*/outputConfig, /*commandConfig=*/commandConfig, /*target=*/nullptr); - cm::append(depends, cmExpandedList(ep)); + cm::append(depends, cmList{ ep }); } for (std::string& p : depends) { if (cmSystemTools::FileIsFullPath(p)) { @@ -196,7 +197,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( clarg, ge, this->LG, useOutputConfig, this->OutputConfig, this->CommandConfig, target, &this->Utilities); if (this->CC->GetCommandExpandLists()) { - cm::append(argv, cmExpandedList(parsed_arg)); + cm::append(argv, cmList{ parsed_arg }); } else { argv.push_back(std::move(parsed_arg)); } diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index eca1abdaae..04bccce5e7 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -9,6 +9,7 @@ #include "cmFileTime.h" #include "cmFileTimeCache.h" #include "cmGeneratedFileStream.h" +#include "cmList.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -28,11 +29,11 @@ bool cmDepends::Write(std::ostream& makeDepends, std::ostream& internalDepends) std::map<std::string, std::set<std::string>> dependencies; { // Lookup the set of sources to scan. - std::vector<std::string> pairs; + cmList pairs; { std::string const srcLang = "CMAKE_DEPENDS_CHECK_" + this->Language; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - cmExpandList(mf->GetSafeDefinition(srcLang), pairs); + pairs.assign(mf->GetSafeDefinition(srcLang)); } for (auto si = pairs.begin(); si != pairs.end();) { // Get the source and object file. diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 25278090a4..408a85b325 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -8,6 +8,7 @@ #include "cmFileTime.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmList.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -393,10 +394,10 @@ void cmDependsC::Scan(std::istream& is, const std::string& directory, void cmDependsC::SetupTransforms() { // Get the transformation rules. - std::vector<std::string> transformRules; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - mf->GetDefExpandList("CMAKE_INCLUDE_TRANSFORMS", transformRules, true); - for (std::string const& tr : transformRules) { + cmList transformRules{ mf->GetDefinition("CMAKE_INCLUDE_TRANSFORMS"), + cmList::EmptyElements::Yes }; + for (auto const& tr : transformRules) { this->ParseTransform(tr); } diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx index 0cc4946e48..c8061c36ee 100644 --- a/Source/cmDependsCompiler.cxx +++ b/Source/cmDependsCompiler.cxx @@ -128,7 +128,7 @@ bool cmDependsCompiler::CheckDependencies( } std::string line; - if (!isValidPath) { + if (!isValidPath && !source.empty()) { // insert source as first dependency depends.push_back(source); } @@ -158,14 +158,16 @@ bool cmDependsCompiler::CheckDependencies( } // ensure source file is the first dependency - if (depends.front() != source) { - cm::erase(depends, source); - if (!isValidPath) { - depends.insert(depends.begin(), source); + if (!source.empty()) { + if (depends.front() != source) { + cm::erase(depends, source); + if (!isValidPath) { + depends.insert(depends.begin(), source); + } + } else if (isValidPath) { + // remove first dependency because it must not be filtered out + depends.erase(depends.begin()); } - } else if (isValidPath) { - // remove first dependency because it must not be filtered out - depends.erase(depends.begin()); } } else { // unknown format, ignore it @@ -174,8 +176,10 @@ bool cmDependsCompiler::CheckDependencies( if (isValidPath) { cm::erase_if(depends, isValidPath); - // insert source as first dependency - depends.insert(depends.begin(), source); + if (!source.empty()) { + // insert source as first dependency + depends.insert(depends.begin(), source); + } } dependencies[target] = std::move(depends); diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 718097f0be..aede3fecff 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -13,6 +13,7 @@ #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmGeneratedFileStream.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmList.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmOutputConverter.h" @@ -78,9 +79,8 @@ cmDependsFortran::cmDependsFortran(cmLocalUnixMakefileGenerator3* lg) this->SetIncludePathFromLanguage("Fortran"); // Get the list of definitions. - std::vector<std::string> definitions; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - mf->GetDefExpandList("CMAKE_TARGET_DEFINITIONS_Fortran", definitions); + cmList definitions{ mf->GetDefinition("CMAKE_TARGET_DEFINITIONS_Fortran") }; // translate i.e. FOO=BAR to FOO and add it to the list of defined // preprocessor symbols @@ -244,9 +244,9 @@ bool cmDependsFortran::LocateModules() // Load information about other targets. cmMakefile* mf = this->LocalGenerator->GetMakefile(); - std::vector<std::string> infoFiles; - mf->GetDefExpandList("CMAKE_Fortran_TARGET_LINKED_INFO_FILES", infoFiles); - for (std::string const& i : infoFiles) { + cmList infoFiles{ mf->GetDefinition( + "CMAKE_Fortran_TARGET_LINKED_INFO_FILES") }; + for (auto const& i : infoFiles) { std::string targetDir = cmSystemTools::GetFilenamePath(i); std::string fname = targetDir + "/fortran.internal"; cmsys::ifstream fin(fname.c_str()); diff --git a/Source/cmEvaluatedTargetProperty.cxx b/Source/cmEvaluatedTargetProperty.cxx index 1173690318..b82c29b75c 100644 --- a/Source/cmEvaluatedTargetProperty.cxx +++ b/Source/cmEvaluatedTargetProperty.cxx @@ -8,7 +8,7 @@ #include "cmGeneratorExpressionContext.h" #include "cmGeneratorTarget.h" #include "cmLinkItem.h" -#include "cmStringAlgorithms.h" +#include "cmList.h" struct cmGeneratorExpressionDAGChecker; diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index 5d0b208931..5e7008b957 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -10,6 +10,7 @@ #include "cmGeneratorTarget.h" #include "cmLinkItem.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -148,7 +149,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( } } else if (property.first == "INTERFACE_INCLUDE_DIRECTORIES") { std::string includes = property.second; - std::vector<std::string> includeList = cmExpandedList(includes); + cmList includeList{ includes }; os << "LOCAL_EXPORT_C_INCLUDES := "; std::string end; for (std::string const& i : includeList) { @@ -158,9 +159,8 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( os << "\n"; } else if (property.first == "INTERFACE_LINK_OPTIONS") { os << "LOCAL_EXPORT_LDFLAGS := "; - std::vector<std::string> linkFlagsList = - cmExpandedList(property.second); - os << cmJoin(linkFlagsList, " ") << "\n"; + cmList linkFlagsList{ property.second }; + os << linkFlagsList.join(" ") << "\n"; } else { os << "# " << property.first << " " << (property.second) << "\n"; } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index e997158c3e..22276ae508 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmLinkItem.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -507,7 +508,7 @@ static void getPropertyContents(cmGeneratorTarget const* tgt, if (!p) { return; } - std::vector<std::string> content = cmExpandedList(*p); + cmList content{ *p }; ifaceProperties.insert(content.begin(), content.end()); } @@ -1261,7 +1262,7 @@ bool cmExportFileGenerator::PopulateExportProperties( const auto& targetProperties = gte->Target->GetProperties(); if (cmValue exportProperties = targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) { - for (auto& prop : cmExpandedList(*exportProperties)) { + for (auto& prop : cmList{ *exportProperties }) { /* Black list reserved properties */ if (cmHasLiteralPrefix(prop, "IMPORTED_") || cmHasLiteralPrefix(prop, "INTERFACE_")) { @@ -1325,7 +1326,22 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte, << this->GetFileSetFiles(gte, fileSet, te) << "\n"; } - os << " )\nendif()\n\n"; + os << " )\nelse()\n set_property(TARGET " << targetName + << "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES"; + for (auto const& name : interfaceFileSets) { + auto* fileSet = gte->Target->GetFileSet(name); + if (!fileSet) { + gte->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("File set \"", name, + "\" is listed in interface file sets of ", gte->GetName(), + " but has not been created")); + return; + } + + os << "\n " << this->GetFileSetDirectories(gte, fileSet, te); + } + os << "\n )\nendif()\n\n"; } } diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index c6ebad5c2d..f30c3c3ba4 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -12,6 +12,7 @@ #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -126,7 +127,7 @@ void cmExportTryCompileFileGenerator::PopulateProperties( std::string evalResult = this->FindTargets(p, target, std::string(), emitted); - std::vector<std::string> depends = cmExpandedList(evalResult); + cmList depends{ evalResult }; for (std::string const& li : depends) { cmGeneratorTarget* tgt = target->GetLocalGenerator()->FindGeneratorTargetToUse(li); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index e9e2921316..8d7f33e7ef 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -14,6 +14,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmRange.h" @@ -567,13 +568,13 @@ void cmExtraCodeBlocksGenerator::AppendTarget( std::string systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cm::append(allIncludeDirs, cmExpandedList(systemIncludeDirs)); + cm::append(allIncludeDirs, cmList{ systemIncludeDirs }); } systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cm::append(allIncludeDirs, cmExpandedList(systemIncludeDirs)); + cm::append(allIncludeDirs, cmList{ systemIncludeDirs }); } auto end = cmRemoveDuplicates(allIncludeDirs); diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 6201889f22..c7ce5b0676 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -16,6 +16,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -418,7 +419,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() if (cmValue extraNaturesProp = mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) { - std::vector<std::string> extraNatures = cmExpandedList(*extraNaturesProp); + cmList extraNatures{ *extraNaturesProp }; for (std::string const& n : extraNatures) { xml.Element("nature", n); } @@ -798,7 +799,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS"); if (this->CEnabled && cDefs) { // Expand the list. - std::vector<std::string> defs = cmExpandedList(*cDefs, true); + cmList defs{ *cDefs, cmList::EmptyElements::Yes }; // the list must contain only definition-value pairs: if ((defs.size() % 2) == 0) { @@ -830,7 +831,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS"); if (this->CXXEnabled && cxxDefs) { // Expand the list. - std::vector<std::string> defs = cmExpandedList(*cxxDefs, true); + cmList defs{ *cxxDefs, cmList::EmptyElements::Yes }; // the list must contain only definition-value pairs: if ((defs.size() % 2) == 0) { @@ -879,14 +880,14 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const if (this->CEnabled && !compiler.empty()) { std::string systemIncludeDirs = mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); - std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs); + cmList dirs{ systemIncludeDirs }; this->AppendIncludeDirectories(xml, dirs, emitted); } compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); if (this->CXXEnabled && !compiler.empty()) { std::string systemIncludeDirs = mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); - std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs); + cmList dirs{ systemIncludeDirs }; this->AppendIncludeDirectories(xml, dirs, emitted); } diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 33901ac594..205a691f21 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -14,6 +14,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -138,7 +139,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile( // End of build_systems fout << "\n\t]"; std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); - std::vector<std::string> tokens = cmExpandedList(this->EnvSettings); + cmList tokens{ this->EnvSettings }; if (!this->EnvSettings.empty()) { fout << ","; diff --git a/Source/cmFileAPIToolchains.cxx b/Source/cmFileAPIToolchains.cxx index fe2972fabf..a51ae2048e 100644 --- a/Source/cmFileAPIToolchains.cxx +++ b/Source/cmFileAPIToolchains.cxx @@ -10,6 +10,7 @@ #include "cmFileAPI.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -124,10 +125,11 @@ void Toolchains::DumpToolchainVariable(cmMakefile const* mf, cmStrCat("CMAKE_", lang, "_", variable.VariableSuffix); if (variable.IsList) { - std::vector<std::string> values; - if (mf->GetDefExpandList(variableName, values)) { + cmValue data = mf->GetDefinition(variableName); + if (data) { + cmList values(data); Json::Value jsonArray = Json::arrayValue; - for (std::string const& value : values) { + for (auto const& value : values) { jsonArray.append(value); } object[variable.ObjectKey] = jsonArray; diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index ef55abfd14..663bddcece 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -9,6 +9,7 @@ #include "cmExecutionStatus.h" #include "cmFSPermissions.h" #include "cmFileTimes.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -169,8 +170,7 @@ bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode) cmValue default_dir_install_permissions = this->Makefile->GetDefinition( "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_install_permissions)) { - std::vector<std::string> items = - cmExpandedList(*default_dir_install_permissions); + cmList items{ *default_dir_install_permissions }; for (const auto& arg : items) { if (!this->CheckPermissions(arg, **mode)) { this->Status.SetError( diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx index b96ba6e886..48a2570d56 100644 --- a/Source/cmFileSet.cxx +++ b/Source/cmFileSet.cxx @@ -12,6 +12,7 @@ #include "cmsys/RegularExpression.hxx" #include "cmGeneratorExpression.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -113,7 +114,7 @@ cmFileSet::CompileFileEntries() const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result; for (auto const& entry : this->FileEntries) { - for (auto const& ex : cmExpandedList(entry.Value)) { + for (auto const& ex : cmList{ entry.Value }) { cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace); auto cge = ge.Parse(ex); result.push_back(std::move(cge)); @@ -129,7 +130,7 @@ cmFileSet::CompileDirectoryEntries() const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result; for (auto const& entry : this->DirectoryEntries) { - for (auto const& ex : cmExpandedList(entry.Value)) { + for (auto const& ex : cmList{ entry.Value }) { cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace); auto cge = ge.Parse(ex); result.push_back(std::move(cge)); @@ -148,7 +149,7 @@ std::vector<std::string> cmFileSet::EvaluateDirectoryEntries( std::vector<std::string> result; for (auto const& cge : cges) { auto entry = cge->Evaluate(lg, config, target, dagChecker); - auto dirs = cmExpandedList(entry); + cmList dirs{ entry }; for (std::string dir : dirs) { if (!cmSystemTools::FileIsFullPath(dir)) { dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir); @@ -184,7 +185,7 @@ void cmFileSet::EvaluateFileEntry( cmGeneratorExpressionDAGChecker* dagChecker) const { auto files = cge->Evaluate(lg, config, target, dagChecker); - for (std::string file : cmExpandedList(files)) { + for (std::string file : cmList{ files }) { if (!cmSystemTools::FileIsFullPath(file)) { file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file); } diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 4df81d5773..929c6c1c82 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -15,6 +15,7 @@ #include "cmCMakePath.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -154,7 +155,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) } // ensure a macro is not specified as validator const auto& validatorName = args[j]; - auto macros = cmExpandedList(this->Makefile->GetProperty("MACROS")); + cmList macros{ this->Makefile->GetProperty("MACROS") }; if (std::find_if(macros.begin(), macros.end(), [&validatorName](const std::string& item) { return cmSystemTools::Strucmp(validatorName.c_str(), @@ -403,7 +404,7 @@ void cmFindBase::FillCMakeSystemVariablePath() this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH"); // remove entries from CMAKE_SYSTEM_PREFIX_PATH - std::vector<std::string> expanded = cmExpandedList(*prefix_paths); + cmList expanded{ *prefix_paths }; install_entry.remove_self(expanded); staging_entry.remove_self(expanded); diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index c3fb9077da..bec6369211 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -9,6 +9,7 @@ #include <cmext/algorithm> #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -238,9 +239,9 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) } // Construct the list of path roots with no trailing slashes. - std::vector<std::string> roots; + cmList roots; if (rootPath) { - cmExpandList(*rootPath, roots); + roots.assign(*rootPath); } if (sysrootCompile) { roots.emplace_back(*sysrootCompile); @@ -251,14 +252,14 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) if (sysroot) { roots.emplace_back(*sysroot); } - for (std::string& r : roots) { + for (auto& r : roots) { cmSystemTools::ConvertToUnixSlashes(r); } cmValue stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); // Copy the original set of unrooted paths. - std::vector<std::string> unrootedPaths = paths; + auto unrootedPaths = paths; paths.clear(); auto isSameDirectoryOrSubDirectory = [](std::string const& l, @@ -267,8 +268,8 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) cmSystemTools::IsSubDirectory(l, r); }; - for (std::string const& r : roots) { - for (std::string const& up : unrootedPaths) { + for (auto const& r : roots) { + for (auto const& up : unrootedPaths) { // Place the unrooted path under the current root if it is not // already inside. Skip the unrooted path if it is relative to // a user home directory or is empty. @@ -308,7 +309,7 @@ void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore) // Construct the list of path roots with no trailing slashes. for (const char* pathName : paths) { // Get the list of paths to ignore from the variable. - this->Makefile->GetDefExpandList(pathName, ignore); + cmList::append(ignore, this->Makefile->GetDefinition(pathName)); } for (std::string& i : ignore) { @@ -333,7 +334,7 @@ void cmFindCommon::GetIgnoredPrefixPaths(std::vector<std::string>& ignore) // Construct the list of path roots with no trailing slashes. for (const char* pathName : paths) { // Get the list of paths to ignore from the variable. - this->Makefile->GetDefExpandList(pathName, ignore); + cmList::append(ignore, this->Makefile->GetDefinition(pathName)); } for (std::string& i : ignore) { diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 6296a60aeb..9eb060357a 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -11,6 +11,7 @@ #include "cmsys/RegularExpression.hxx" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" @@ -196,8 +197,8 @@ struct cmFindLibraryHelper cmGlobalGenerator* GG; // List of valid prefixes and suffixes. - std::vector<std::string> Prefixes; - std::vector<std::string> Suffixes; + cmList Prefixes; + cmList Suffixes; std::string PrefixRegexStr; std::string SuffixRegexStr; @@ -223,7 +224,7 @@ struct cmFindLibraryHelper std::string TestPath; void RegexFromLiteral(std::string& out, std::string const& in); - void RegexFromList(std::string& out, std::vector<std::string> const& in); + void RegexFromList(std::string& out, cmList const& in); size_type GetPrefixIndex(std::string const& prefix) { return std::find(this->Prefixes.begin(), this->Prefixes.end(), prefix) - @@ -307,8 +308,8 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, std::string const& prefixes_list = get_prefixes(this->Makefile); std::string const& suffixes_list = get_suffixes(this->Makefile); - cmExpandList(prefixes_list, this->Prefixes, true); - cmExpandList(suffixes_list, this->Suffixes, true); + this->Prefixes.assign(prefixes_list, cmList::EmptyElements::Yes); + this->Suffixes.assign(suffixes_list, cmList::EmptyElements::Yes); this->RegexFromList(this->PrefixRegexStr, this->Prefixes); this->RegexFromList(this->SuffixRegexStr, this->Suffixes); @@ -334,14 +335,13 @@ void cmFindLibraryHelper::RegexFromLiteral(std::string& out, } } -void cmFindLibraryHelper::RegexFromList(std::string& out, - std::vector<std::string> const& in) +void cmFindLibraryHelper::RegexFromList(std::string& out, cmList const& in) { // Surround the list in parens so the '|' does not apply to anything // else and the result can be checked after matching. out += "("; const char* sep = ""; - for (std::string const& s : in) { + for (auto const& s : in) { // Separate from previous item. out += sep; sep = "|"; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index b1029e62c8..98b085cdc0 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -23,6 +23,7 @@ #include "cmAlgorithms.h" #include "cmDependencyProvider.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -1781,28 +1782,20 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f, void cmFindPackageCommand::AppendToFoundProperty(const bool found) { - std::vector<std::string> foundContents; + cmList foundContents; cmValue foundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND"); - if (cmNonempty(foundProp)) { - cmExpandList(*foundProp, foundContents, false); - auto nameIt = - std::find(foundContents.begin(), foundContents.end(), this->Name); - if (nameIt != foundContents.end()) { - foundContents.erase(nameIt); - } + if (!foundProp.IsEmpty()) { + foundContents.assign(*foundProp); + foundContents.remove_items({ this->Name }); } - std::vector<std::string> notFoundContents; + cmList notFoundContents; cmValue notFoundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND"); - if (cmNonempty(notFoundProp)) { - cmExpandList(*notFoundProp, notFoundContents, false); - auto nameIt = - std::find(notFoundContents.begin(), notFoundContents.end(), this->Name); - if (nameIt != notFoundContents.end()) { - notFoundContents.erase(nameIt); - } + if (!notFoundProp.IsEmpty()) { + notFoundContents.assign(*notFoundProp); + notFoundContents.remove_items({ this->Name }); } if (found) { @@ -1811,12 +1804,11 @@ void cmFindPackageCommand::AppendToFoundProperty(const bool found) notFoundContents.push_back(this->Name); } - std::string tmp = cmJoin(foundContents, ";"); - this->Makefile->GetState()->SetGlobalProperty("PACKAGES_FOUND", tmp.c_str()); + this->Makefile->GetState()->SetGlobalProperty( + "PACKAGES_FOUND", foundContents.to_string().c_str()); - tmp = cmJoin(notFoundContents, ";"); - this->Makefile->GetState()->SetGlobalProperty("PACKAGES_NOT_FOUND", - tmp.c_str()); + this->Makefile->GetState()->SetGlobalProperty( + "PACKAGES_NOT_FOUND", notFoundContents.to_string().c_str()); } void cmFindPackageCommand::AppendSuccessInformation() @@ -2338,7 +2330,7 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() cmValue prefix_paths = this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH"); // remove entry from CMAKE_SYSTEM_PREFIX_PATH - std::vector<std::string> expanded = cmExpandedList(*prefix_paths); + cmList expanded{ *prefix_paths }; long count = 0; for (const auto& path : expanded) { bool const to_add = diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 3465c230f8..21a140d02c 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -23,6 +23,7 @@ #include "cmExecutionStatus.h" #include "cmFunctionBlocker.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -156,16 +157,16 @@ bool cmForEachFunctionBlocker::ReplayZipLists( auto& mf = inStatus.GetMakefile(); // Expand the list of list-variables into a list of lists of strings - std::vector<std::vector<std::string>> values; + std::vector<cmList> values; values.reserve(this->Args.size() - this->IterationVarsCount); // Also track the longest list size std::size_t maxItems = 0u; for (auto const& var : cmMakeRange(this->Args).advance(this->IterationVarsCount)) { - std::vector<std::string> items; + cmList items; auto const& value = mf.GetSafeDefinition(var); if (!value.empty()) { - cmExpandList(value, items, true); + items.assign(value, cmList::EmptyElements::Yes); } maxItems = std::max(maxItems, items.size()); values.emplace_back(std::move(items)); @@ -344,7 +345,7 @@ bool HandleInMode(std::vector<std::string> const& args, } else if (doing == DoingLists) { auto const& value = makefile.GetSafeDefinition(arg); if (!value.empty()) { - cmExpandList(value, fb->Args, true); + cmExpandList(value, fb->Args, cmList::EmptyElements::Yes); } } else if (doing == DoingItems || doing == DoingZipLists) { diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx index 34c88248a0..87377de401 100644 --- a/Source/cmGccDepfileLexerHelper.cxx +++ b/Source/cmGccDepfileLexerHelper.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGccDepfileLexerHelper.h" +#include <algorithm> #include <cstdio> #include <memory> #include <string> @@ -113,6 +114,11 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s) void cmGccDepfileLexerHelper::sanitizeContent() { for (auto it = this->Content.begin(); it != this->Content.end();) { + // remove duplicate path entries + std::sort(it->paths.begin(), it->paths.end()); + auto last = std::unique(it->paths.begin(), it->paths.end()); + it->paths.erase(last, it->paths.end()); + // Remove empty paths and normalize windows paths for (auto pit = it->paths.begin(); pit != it->paths.end();) { if (pit->empty()) { diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index c5ae31bd38..04decd239c 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -14,6 +14,7 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionLexer.h" #include "cmGeneratorExpressionParser.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index ca61f75ffa..bb4fc7e271 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -19,7 +19,6 @@ #include <cm/iterator> #include <cm/optional> #include <cm/string_view> -#include <cm/vector> #include <cmext/algorithm> #include <cmext/string_view> @@ -635,22 +634,48 @@ public: using Arguments = Range<std::vector<std::string>>; -bool CheckPathParametersEx(cmGeneratorExpressionContext* ctx, - const GeneratorExpressionContent* cnt, - cm::string_view option, std::size_t count, - int required = 1, bool exactly = true) +bool CheckGenExParameters(cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + cm::string_view genex, cm::string_view option, + std::size_t count, int required = 1, + bool exactly = true) { if (static_cast<int>(count) < required || (exactly && static_cast<int>(count) > required)) { + std::string nbParameters; + switch (required) { + case 1: + nbParameters = "one parameter"; + break; + case 2: + nbParameters = "two parameters"; + break; + case 3: + nbParameters = "three parameters"; + break; + case 4: + nbParameters = "four parameters"; + break; + default: + nbParameters = cmStrCat(std::to_string(required), " parameters"); + } reportError(ctx, cnt->GetOriginalExpression(), - cmStrCat("$<PATH:", option, "> expression requires ", - (exactly ? "exactly" : "at least"), ' ', - (required == 1 ? "one parameter" : "two parameters"), + cmStrCat("$<", genex, ':', option, "> expression requires ", + (exactly ? "exactly" : "at least"), ' ', nbParameters, '.')); return false; } return true; }; + +bool CheckPathParametersEx(cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + cm::string_view option, std::size_t count, + int required = 1, bool exactly = true) +{ + return CheckGenExParameters(ctx, cnt, "PATH"_s, option, count, required, + exactly); +} bool CheckPathParameters(cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, cm::string_view option, const Arguments& args, @@ -658,6 +683,7 @@ bool CheckPathParameters(cmGeneratorExpressionContext* ctx, { return CheckPathParametersEx(ctx, cnt, option, args.size(), required); }; + std::string ToString(bool isTrue) { return isTrue ? "1" : "0"; @@ -681,9 +707,9 @@ static const struct PathNode : public cmGeneratorExpressionNode static auto processList = [](std::string const& arg, std::function<void(std::string&)> transform) -> std::string { - auto list = cmExpandedList(arg); + cmList list{ arg }; std::for_each(list.begin(), list.end(), std::move(transform)); - return cmJoin(list, ";"); + return list.to_string(); }; static std::unordered_map< @@ -1108,6 +1134,675 @@ static const struct PathEqualNode : public cmGeneratorExpressionNode } } pathEqualNode; +namespace { +inline bool CheckListParametersEx(cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + cm::string_view option, std::size_t count, + int required = 1, bool exactly = true) +{ + return CheckGenExParameters(ctx, cnt, "LIST"_s, option, count, required, + exactly); +} +inline bool CheckListParameters(cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + cm::string_view option, const Arguments& args, + int required = 1) +{ + return CheckListParametersEx(ctx, cnt, option, args.size(), required); +}; + +inline cmList GetList(std::string const& list) +{ + return list.empty() ? cmList{} : cmList{ list, cmList::EmptyElements::Yes }; +} + +bool GetNumericArgument(const std::string& arg, cmList::index_type& value) +{ + try { + std::size_t pos; + + if (sizeof(cmList::index_type) == sizeof(long)) { + value = std::stol(arg, &pos); + } else { + value = std::stoll(arg, &pos); + } + + if (pos != arg.length()) { + // this is not a number + return false; + } + } catch (const std::invalid_argument&) { + return false; + } + + return true; +} + +bool GetNumericArguments( + cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, + Arguments const& args, std::vector<cmList::index_type>& indexes, + cmList::ExpandElements expandElements = cmList::ExpandElements::No) +{ + using IndexRange = cmRange<Arguments::const_iterator>; + IndexRange arguments(args.begin(), args.end()); + cmList list; + if (expandElements == cmList::ExpandElements::Yes) { + list = cmList{ args.begin(), args.end(), expandElements }; + arguments = IndexRange{ list.begin(), list.end() }; + } + + for (auto const& value : arguments) { + cmList::index_type index; + if (!GetNumericArgument(value, index)) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("index: \"", value, "\" is not a valid index")); + return false; + } + indexes.push_back(index); + } + return true; +} +} + +static const struct ListNode : public cmGeneratorExpressionNode +{ + ListNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return TwoOrMoreParameters; } + + bool AcceptsArbitraryContentParameter() const override { return true; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + static std::unordered_map< + cm::string_view, + std::function<std::string(cmGeneratorExpressionContext*, + const GeneratorExpressionContent*, + Arguments&)>> + listCommands{ + { "LENGTH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "LENGTH"_s, args)) { + return std::to_string(GetList(args.front()).size()); + } + return std::string{}; + } }, + { "GET"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "GET"_s, args.size(), 2, + false)) { + auto list = GetList(args.front()); + if (list.empty()) { + reportError(ctx, cnt->GetOriginalExpression(), + "given empty list"); + return std::string{}; + } + + std::vector<cmList::index_type> indexes; + if (!GetNumericArguments(ctx, cnt, args.advance(1), indexes, + cmList::ExpandElements::Yes)) { + return std::string{}; + } + try { + return list.get_items(indexes.begin(), indexes.end()) + .to_string(); + } catch (std::out_of_range& e) { + reportError(ctx, cnt->GetOriginalExpression(), e.what()); + return std::string{}; + } + } + return std::string{}; + } }, + { "JOIN"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "JOIN"_s, args, 2)) { + return GetList(args.front()).join(args[1]); + } + return std::string{}; + } }, + { "SUBLIST"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "SUBLIST"_s, args, 3)) { + auto list = GetList(args.front()); + if (!list.empty()) { + std::vector<cmList::index_type> indexes; + if (!GetNumericArguments(ctx, cnt, args.advance(1), indexes)) { + return std::string{}; + } + if (indexes[0] < 0) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("begin index: ", indexes[0], + " is out of range 0 - ", + list.size() - 1)); + return std::string{}; + } + if (indexes[1] < -1) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("length: ", indexes[1], + " should be -1 or greater")); + return std::string{}; + } + try { + return list + .sublist(static_cast<cmList::size_type>(indexes[0]), + static_cast<cmList::size_type>(indexes[1])) + .to_string(); + } catch (std::out_of_range& e) { + reportError(ctx, cnt->GetOriginalExpression(), e.what()); + return std::string{}; + } + } + } + return std::string{}; + } }, + { "FIND"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "FIND"_s, args, 2)) { + auto list = GetList(args.front()); + auto index = list.find(args[1]); + return index == cmList::npos ? "-1" : std::to_string(index); + } + return std::string{}; + } }, + { "APPEND"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "APPEND"_s, args.size(), 2, + false)) { + auto list = args.front(); + args.advance(1); + return cmList::append(list, args.begin(), args.end()); + } + return std::string{}; + } }, + { "PREPEND"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "PREPEND"_s, args.size(), 2, + false)) { + auto list = args.front(); + args.advance(1); + return cmList::prepend(list, args.begin(), args.end()); + } + return std::string{}; + } }, + { "INSERT"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "INSERT"_s, args.size(), 3, + false)) { + cmList::index_type index; + if (!GetNumericArgument(args[1], index)) { + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat("index: \"", args[1], "\" is not a valid index")); + return std::string{}; + } + try { + auto list = GetList(args.front()); + args.advance(2); + list.insert_items(index, args.begin(), args.end()); + return list.to_string(); + } catch (std::out_of_range& e) { + reportError(ctx, cnt->GetOriginalExpression(), e.what()); + return std::string{}; + } + } + return std::string{}; + } }, + { "POP_BACK"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "POP_BACK"_s, args)) { + auto list = GetList(args.front()); + if (!list.empty()) { + list.pop_back(); + return list.to_string(); + } + } + return std::string{}; + } }, + { "POP_FRONT"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "POP_FRONT"_s, args)) { + auto list = GetList(args.front()); + if (!list.empty()) { + list.pop_front(); + return list.to_string(); + } + } + return std::string{}; + } }, + { "REMOVE_DUPLICATES"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "REMOVE_DUPLICATES"_s, args)) { + return GetList(args.front()).remove_duplicates().to_string(); + } + return std::string{}; + } }, + { "REMOVE_ITEM"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "REMOVE_ITEM"_s, args.size(), + 2, false)) { + auto list = GetList(args.front()); + args.advance(1); + cmList items{ args.begin(), args.end(), + cmList::ExpandElements::Yes }; + return list.remove_items(items.begin(), items.end()).to_string(); + } + return std::string{}; + } }, + { "REMOVE_AT"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "REMOVE_AT"_s, args.size(), 2, + false)) { + auto list = GetList(args.front()); + std::vector<cmList::index_type> indexes; + if (!GetNumericArguments(ctx, cnt, args.advance(1), indexes, + cmList::ExpandElements::Yes)) { + return std::string{}; + } + try { + return list.remove_items(indexes.begin(), indexes.end()) + .to_string(); + } catch (std::out_of_range& e) { + reportError(ctx, cnt->GetOriginalExpression(), e.what()); + return std::string{}; + } + } + return std::string{}; + } }, + { "FILTER"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "FILTER"_s, args, 3)) { + auto const& op = args[1]; + if (op != "INCLUDE"_s && op != "EXCLUDE"_s) { + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command FILTER does not recognize operator \"", + op, "\". It must be either INCLUDE or EXCLUDE.")); + return std::string{}; + } + try { + return GetList(args.front()) + .filter(args[2], + op == "INCLUDE"_s ? cmList::FilterMode::INCLUDE + : cmList::FilterMode::EXCLUDE) + .to_string(); + } catch (std::invalid_argument&) { + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command FILTER, failed to compile regex \"", + args[2], "\".")); + return std::string{}; + } + } + return std::string{}; + } }, + { "TRANSFORM"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "TRANSFORM"_s, args.size(), 2, + false)) { + auto list = GetList(args.front()); + if (!list.empty()) { + struct ActionDescriptor + { + ActionDescriptor(std::string name) + : Name(std::move(name)) + { + } + ActionDescriptor(std::string name, + cmList::TransformAction action, int arity) + : Name(std::move(name)) + , Action(action) + , Arity(arity) + { + } + + operator const std::string&() const { return this->Name; } + + std::string Name; + cmList::TransformAction Action; + int Arity = 0; + }; + + static std::set< + ActionDescriptor, + std::function<bool(const std::string&, const std::string&)>> + descriptors{ + { { "APPEND", cmList::TransformAction::APPEND, 1 }, + { "PREPEND", cmList::TransformAction::PREPEND, 1 }, + { "TOUPPER", cmList::TransformAction::TOUPPER, 0 }, + { "TOLOWER", cmList::TransformAction::TOLOWER, 0 }, + { "STRIP", cmList::TransformAction::STRIP, 0 }, + { "REPLACE", cmList::TransformAction::REPLACE, 2 } }, + [](const std::string& x, const std::string& y) { + return x < y; + } + }; + + auto descriptor = descriptors.find(args.advance(1).front()); + if (descriptor == descriptors.end()) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat(" sub-command TRANSFORM, ", + args.front(), " invalid action.")); + return std::string{}; + } + + // Action arguments + args.advance(1); + if (args.size() < descriptor->Arity) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command TRANSFORM, action ", + descriptor->Name, " expects ", + descriptor->Arity, " argument(s).")); + return std::string{}; + } + std::vector<std::string> arguments; + if (descriptor->Arity > 0) { + arguments = std::vector<std::string>( + args.begin(), args.begin() + descriptor->Arity); + args.advance(descriptor->Arity); + } + + const std::string REGEX{ "REGEX" }; + const std::string AT{ "AT" }; + const std::string FOR{ "FOR" }; + std::unique_ptr<cmList::TransformSelector> selector; + + try { + // handle optional arguments + while (!args.empty()) { + if ((args.front() == REGEX || args.front() == AT || + args.front() == FOR) && + selector) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command TRANSFORM, selector " + "already specified (", + selector->GetTag(), ").")); + + return std::string{}; + } + + // REGEX selector + if (args.front() == REGEX) { + if (args.advance(1).empty()) { + reportError( + ctx, cnt->GetOriginalExpression(), + "sub-command TRANSFORM, selector REGEX expects " + "'regular expression' argument."); + return std::string{}; + } + + selector = cmList::TransformSelector::New< + cmList::TransformSelector::REGEX>(args.front()); + + args.advance(1); + continue; + } + + // AT selector + if (args.front() == AT) { + args.advance(1); + // get all specified indexes + std::vector<cmList::index_type> indexes; + while (!args.empty()) { + cmList indexList{ args.front() }; + for (auto const& index : indexList) { + cmList::index_type value; + + if (!GetNumericArgument(index, value)) { + // this is not a number, stop processing + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command TRANSFORM, selector AT: '", + index, "': unexpected argument.")); + return std::string{}; + } + indexes.push_back(value); + } + args.advance(1); + } + + if (indexes.empty()) { + reportError(ctx, cnt->GetOriginalExpression(), + "sub-command TRANSFORM, selector AT " + "expects at least one " + "numeric value."); + return std::string{}; + } + + selector = cmList::TransformSelector::New< + cmList::TransformSelector::AT>(std::move(indexes)); + + continue; + } + + // FOR selector + if (args.front() == FOR) { + if (args.advance(1).size() < 2) { + reportError(ctx, cnt->GetOriginalExpression(), + "sub-command TRANSFORM, selector FOR " + "expects, at least," + " two arguments."); + return std::string{}; + } + + cmList::index_type start = 0; + cmList::index_type stop = 0; + cmList::index_type step = 1; + bool valid = false; + + if (GetNumericArgument(args.front(), start) && + GetNumericArgument(args.advance(1).front(), stop)) { + valid = true; + } + + if (!valid) { + reportError( + ctx, cnt->GetOriginalExpression(), + "sub-command TRANSFORM, selector FOR expects, " + "at least, two numeric values."); + return std::string{}; + } + // try to read a third numeric value for step + if (!args.advance(1).empty()) { + if (!GetNumericArgument(args.front(), step)) { + // this is not a number + step = -1; + } + args.advance(1); + } + + if (step <= 0) { + reportError( + ctx, cnt->GetOriginalExpression(), + "sub-command TRANSFORM, selector FOR expects " + "positive numeric value for <step>."); + return std::string{}; + } + + selector = cmList::TransformSelector::New< + cmList::TransformSelector::FOR>({ start, stop, step }); + continue; + } + + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command TRANSFORM, '", + cmJoin(args, ", "), + "': unexpected argument(s).")); + return std::string{}; + } + + return list + .transform(descriptor->Action, arguments, + std::move(selector)) + .to_string(); + } catch (cmList::transform_error& e) { + reportError(ctx, cnt->GetOriginalExpression(), e.what()); + return std::string{}; + } + } + } + return std::string{}; + } }, + { "REVERSE"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParameters(ctx, cnt, "REVERSE"_s, args)) { + return GetList(args.front()).reverse().to_string(); + } + return std::string{}; + } }, + { "SORT"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckListParametersEx(ctx, cnt, "SORT"_s, args.size(), 1, + false)) { + auto list = GetList(args.front()); + args.advance(1); + const auto COMPARE = "COMPARE:"_s; + const auto CASE = "CASE:"_s; + const auto ORDER = "ORDER:"_s; + using SortConfig = cmList::SortConfiguration; + SortConfig sortConfig; + for (auto const& arg : args) { + if (cmHasPrefix(arg, COMPARE)) { + if (sortConfig.Compare != + SortConfig::CompareMethod::DEFAULT) { + reportError(ctx, cnt->GetOriginalExpression(), + "sub-command SORT, COMPARE option has been " + "specified multiple times."); + return std::string{}; + } + auto option = + cm::string_view{ arg.c_str() + COMPARE.length() }; + if (option == "STRING"_s) { + sortConfig.Compare = SortConfig::CompareMethod::STRING; + continue; + } + if (option == "FILE_BASENAME"_s) { + sortConfig.Compare = + SortConfig::CompareMethod::FILE_BASENAME; + continue; + } + if (option == "NATURAL"_s) { + sortConfig.Compare = SortConfig::CompareMethod::NATURAL; + continue; + } + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat( + "sub-command SORT, an invalid COMPARE option has been " + "specified: \"", + option, "\".")); + return std::string{}; + } + if (cmHasPrefix(arg, CASE)) { + if (sortConfig.Case != + SortConfig::CaseSensitivity::DEFAULT) { + reportError(ctx, cnt->GetOriginalExpression(), + "sub-command SORT, CASE option has been " + "specified multiple times."); + return std::string{}; + } + auto option = cm::string_view{ arg.c_str() + CASE.length() }; + if (option == "SENSITIVE"_s) { + sortConfig.Case = SortConfig::CaseSensitivity::SENSITIVE; + continue; + } + if (option == "INSENSITIVE"_s) { + sortConfig.Case = SortConfig::CaseSensitivity::INSENSITIVE; + continue; + } + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat( + "sub-command SORT, an invalid CASE option has been " + "specified: \"", + option, "\".")); + return std::string{}; + } + if (cmHasPrefix(arg, ORDER)) { + if (sortConfig.Order != SortConfig::OrderMode::DEFAULT) { + reportError(ctx, cnt->GetOriginalExpression(), + "sub-command SORT, ORDER option has been " + "specified multiple times."); + return std::string{}; + } + auto option = + cm::string_view{ arg.c_str() + ORDER.length() }; + if (option == "ASCENDING"_s) { + sortConfig.Order = SortConfig::OrderMode::ASCENDING; + continue; + } + if (option == "DESCENDING"_s) { + sortConfig.Order = SortConfig::OrderMode::DESCENDING; + continue; + } + reportError( + ctx, cnt->GetOriginalExpression(), + cmStrCat( + "sub-command SORT, an invalid ORDER option has been " + "specified: \"", + option, "\".")); + return std::string{}; + } + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("sub-command SORT, option \"", arg, + "\" is invalid.")); + return std::string{}; + } + + return list.sort(sortConfig).to_string(); + } + return std::string{}; + } } + }; + + if (cm::contains(listCommands, parameters.front())) { + auto args = Arguments{ parameters }.advance(1); + return listCommands[parameters.front()](context, content, args); + } + + reportError(context, content->GetOriginalExpression(), + cmStrCat(parameters.front(), ": invalid option.")); + return std::string{}; + } +} listNode; + static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode { MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default) @@ -1472,11 +2167,11 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode // This imported target has an appropriate location // for this (possibly mapped) config. // Check if there is a proper config mapping for the tested config. - std::vector<std::string> mappedConfigs; + cmList mappedConfigs; std::string mapProp = cmStrCat( "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config)); if (cmValue mapValue = context->CurrentTarget->GetProperty(mapProp)) { - cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs); + mappedConfigs.assign(cmSystemTools::UpperCase(*mapValue)); for (auto const& param : parameters) { if (cm::contains(mappedConfigs, cmSystemTools::UpperCase(param))) { @@ -1581,7 +2276,8 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode // reportError(context, content->GetOriginalExpression(), ""); reportError( context, content->GetOriginalExpression(), - "$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets " + "$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary " + "targets " "to specify include directories, compile definitions, and compile " "options. It may not be used with the add_custom_command, " "add_custom_target, or file(GENERATE) commands."); @@ -1726,7 +2422,8 @@ static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode reportError( context, content->GetOriginalExpression(), "$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets " - "to specify link libraries, link directories, link options, and link " + "to specify link libraries, link directories, link options, and " + "link " "depends."); return std::string(); } @@ -1785,8 +2482,7 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode return std::string(); } - std::vector<std::string> list; - cmExpandLists(parameters.begin(), parameters.end(), list); + cmList list{ parameters.begin(), parameters.end() }; if (list.empty()) { reportError( context, content->GetOriginalExpression(), @@ -1871,8 +2567,7 @@ static const struct LinkGroupNode : public cmGeneratorExpressionNode return std::string(); } - std::vector<std::string> list; - cmExpandLists(parameters.begin(), parameters.end(), list); + cmList list{ parameters.begin(), parameters.end() }; if (list.empty()) { reportError( context, content->GetOriginalExpression(), @@ -1962,8 +2657,7 @@ static const struct DeviceLinkNode : public cmGeneratorExpressionNode } if (context->HeadTarget->IsDeviceLink()) { - std::vector<std::string> list; - cmExpandLists(parameters.begin(), parameters.end(), list); + cmList list{ parameters.begin(), parameters.end() }; const auto DL_BEGIN = "<DEVICE_LINK>"_s; const auto DL_END = "</DEVICE_LINK>"_s; cm::erase_if(list, [&](const std::string& item) { @@ -2108,7 +2802,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode reportError( context, content->GetOriginalExpression(), "$<TARGET_PROPERTY:prop> may only be used with binary targets. " - "It may not be used with add_custom_command or add_custom_target. " + "It may not be used with add_custom_command or add_custom_target. " + " " " " "Specify the target to read a property from using the " "$<TARGET_PROPERTY:tgt,prop> signature instead."); @@ -2373,14 +3068,14 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode } } - std::vector<std::string> objects; + cmList objects; if (gt->IsImported()) { cmValue loc = nullptr; cmValue imp = nullptr; std::string suffix; if (gt->Target->GetMappedConfig(context->Config, loc, imp, suffix)) { - cmExpandList(*loc, objects); + objects.assign(*loc); } context->HadContextSensitiveCondition = true; } else { @@ -2398,7 +3093,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode context->HadContextSensitiveCondition = true; } - for (std::string& o : objects) { + for (auto& o : objects) { o = cmStrCat(obj_dir, o); } } @@ -2518,7 +3213,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode } context->HadHeadSensitiveCondition = true; - using LangMap = std::map<std::string, std::vector<std::string>>; + using LangMap = std::map<std::string, cmList>; static LangMap availableFeatures; LangMap testedFeatures; @@ -2540,7 +3235,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode reportError(context, content->GetOriginalExpression(), error); return std::string(); } - cmExpandList(featuresKnown, availableFeatures[lang]); + availableFeatures[lang].assign(featuresKnown); } } @@ -3691,7 +4386,7 @@ static const struct ShellPathNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::vector<std::string> listIn = cmExpandedList(parameters.front()); + cmList listIn{ parameters.front() }; if (listIn.empty()) { reportError(context, content->GetOriginalExpression(), "\"\" is not an absolute path."); @@ -3802,6 +4497,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "IN_LIST", &inListNode }, { "FILTER", &filterNode }, { "REMOVE_DUPLICATES", &removeDuplicatesNode }, + { "LIST", &listNode }, { "LOWER_CASE", &lowerCaseNode }, { "UPPER_CASE", &upperCaseNode }, { "PATH", &pathNode }, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 7e5ef0a7cb..28ba60f4ed 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -36,6 +36,7 @@ #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpressionNode.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -730,6 +731,29 @@ void cmGeneratorTarget::AddIncludeDirectory(const std::string& src, BT<std::string>(src, this->Makefile->GetBacktrace()), true)); } +void cmGeneratorTarget::AddSystemIncludeDirectory(std::string const& inc, + std::string const& lang) +{ + std::string config_upper; + auto const& configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + + for (auto const& config : configs) { + std::string inc_with_config = inc; + if (!config.empty()) { + cmSystemTools::ReplaceString(inc_with_config, "$<CONFIG>", config); + config_upper = cmSystemTools::UpperCase(config); + } + auto const& key = cmStrCat(config_upper, "/", lang); + this->Target->AddSystemIncludeDirectories({ inc_with_config }); + this->SystemIncludesCache[key].emplace_back(inc_with_config); + + // SystemIncludesCache should be sorted so that binary search can be used + std::sort(this->SystemIncludesCache[key].begin(), + this->SystemIncludesCache[key].end()); + } +} + std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( cmSourceFile const* sf) const { @@ -746,14 +770,13 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, const std::string& config, cmGeneratorTarget const* headTarget, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::string>& result, - bool excludeImported, std::string const& language) + cmList& result, bool excludeImported, + std::string const& language) { if (cmValue dirs = depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) { - cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget, - dagChecker, depTgt, language), - result); + result.append(cmGeneratorExpression::Evaluate( + *dirs, lg, config, headTarget, dagChecker, depTgt, language)); } if (!depTgt->GetPropertyAsBool("SYSTEM")) { return; @@ -768,9 +791,8 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, } if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { - cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget, - dagChecker, depTgt, language), - result); + result.append(cmGeneratorExpression::Evaluate( + *dirs, lg, config, headTarget, dagChecker, depTgt, language)); } } } @@ -1264,12 +1286,11 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"); - std::vector<std::string> result; + cmList result; for (std::string const& it : this->Target->GetSystemIncludeDirectories()) { - cmExpandList(cmGeneratorExpression::Evaluate(it, this->LocalGenerator, - config, this, &dagChecker, - nullptr, language), - result); + result.append(cmGeneratorExpression::Evaluate(it, this->LocalGenerator, + config, this, &dagChecker, + nullptr, language)); } std::vector<cmGeneratorTarget const*> const& deps = @@ -1634,20 +1655,20 @@ void AddFileSetEntries(cmGeneratorTarget const* headTarget, EvaluatedTargetPropertyEntries& entries) { for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) { - for (auto const& name : cmExpandedList(entry.Value)) { + for (auto const& name : cmList{ entry.Value }) { auto const* headerSet = headTarget->Target->GetFileSet(name); addFileSetEntry(headTarget, config, dagChecker, headerSet, entries); } } for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) { - for (auto const& name : cmExpandedList(entry.Value)) { + for (auto const& name : cmList{ entry.Value }) { auto const* cxxModuleSet = headTarget->Target->GetFileSet(name); addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries); } } for (auto const& entry : headTarget->Target->GetCxxModuleHeaderSetsEntries()) { - for (auto const& name : cmExpandedList(entry.Value)) { + for (auto const& name : cmList{ entry.Value }) { auto const* cxxModuleHeaderSet = headTarget->Target->GetFileSet(name); addFileSetEntry(headTarget, config, dagChecker, cxxModuleHeaderSet, entries); @@ -1740,8 +1761,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( cmBTStringRange sourceEntries = this->Target->GetSourceEntries(); for (auto const& entry : sourceEntries) { - std::vector<std::string> items = cmExpandedList(entry.Value); - for (std::string const& item : items) { + cmList items{ entry.Value }; + for (auto const& item : items) { if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") && item.back() == '>') { continue; @@ -1752,10 +1773,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( return files; } - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugSources = !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES"); @@ -3105,8 +3124,8 @@ void cmTargetTraceDependencies::Trace() // Queue dependencies added explicitly by the user. if (cmValue additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> objDeps = cmExpandedList(*additionalDeps); - for (std::string& objDep : objDeps) { + cmList objDeps{ *additionalDeps }; + for (auto& objDep : objDeps) { if (cmSystemTools::FileIsFullPath(objDep)) { objDep = cmSystemTools::CollapseFullPath(objDep); } @@ -3299,9 +3318,9 @@ std::string cmGeneratorTarget::GetCompilePDBDirectory( std::vector<std::string> cmGeneratorTarget::GetAppleArchs( std::string const& config, cm::optional<std::string> lang) const { - std::vector<std::string> archVec; + cmList archList; if (!this->IsApple()) { - return archVec; + return std::move(archList.data()); } cmValue archs = nullptr; if (!config.empty()) { @@ -3313,17 +3332,18 @@ std::vector<std::string> cmGeneratorTarget::GetAppleArchs( archs = this->GetProperty("OSX_ARCHITECTURES"); } if (archs) { - cmExpandList(*archs, archVec); + archList.assign(*archs); } - if (archVec.empty() && + if (archList.empty() && // Fall back to a default architecture if no compiler target is set. (!lang || this->Makefile ->GetDefinition(cmStrCat("CMAKE_", *lang, "_COMPILER_TARGET")) .IsEmpty())) { - this->Makefile->GetDefExpandList("_CMAKE_APPLE_ARCHS_DEFAULT", archVec); + archList.assign( + this->Makefile->GetDefinition("_CMAKE_APPLE_ARCHS_DEFAULT")); } - return archVec; + return std::move(archList.data()); } void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags, @@ -3432,10 +3452,9 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(cmBuildStep compileOrLink, std::vector<CudaArchitecture> architectures; { - std::vector<std::string> options; - cmExpandList(property, options); + cmList options(property); - for (std::string& option : options) { + for (auto& option : options) { CudaArchitecture architecture; // Architecture name is up to the first specifier. @@ -3526,8 +3545,7 @@ void cmGeneratorTarget::AddISPCTargetFlags(std::string& flags) const this->Makefile->GetSafeDefinition("CMAKE_ISPC_COMPILER_ID"); if (compiler == "Intel") { - std::vector<std::string> targets; - cmExpandList(property, targets); + cmList targets(property); if (!targets.empty()) { flags += cmStrCat(" --target=", cmWrap("", targets, "", ",")); } @@ -3549,8 +3567,7 @@ void cmGeneratorTarget::AddHIPArchitectureFlags(std::string& flags) const return; } - std::vector<std::string> options; - cmExpandList(property, options); + cmList options(property); for (std::string& option : options) { flags += " --offload-arch=" + option; @@ -3762,10 +3779,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugIncludes = !this->DebugIncludesDone && cm::contains(debugProperties, "INCLUDE_DIRECTORIES"); @@ -4021,10 +4036,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugOptions = !this->DebugCompileOptionsDone && cm::contains(debugProperties, "COMPILE_OPTIONS"); @@ -4064,10 +4077,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugFeatures = !this->DebugCompileFeaturesDone && cm::contains(debugProperties, "COMPILE_FEATURES"); @@ -4116,10 +4127,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugDefines = !this->DebugCompileDefinitionsDone && cm::contains(debugProperties, "COMPILE_DEFINITIONS"); @@ -4182,10 +4191,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders( cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugDefines = !this->DebugPrecompileHeadersDone && std::find(debugProperties.begin(), debugProperties.end(), "PRECOMPILE_HEADERS") != debugProperties.end(); @@ -4579,10 +4586,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugOptions = !this->DebugLinkOptionsDone && cm::contains(debugProperties, "LINK_OPTIONS"); @@ -4606,7 +4611,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( // wrap host link options const std::string wrapper(this->Makefile->GetSafeDefinition( "CMAKE_" + language + "_DEVICE_COMPILER_WRAPPER_FLAG")); - std::vector<std::string> wrapperFlag = cmExpandedList(wrapper); + cmList wrapperFlag{ wrapper }; const std::string wrapperSep(this->Makefile->GetSafeDefinition( "CMAKE_" + language + "_DEVICE_COMPILER_WRAPPER_FLAG_SEP")); bool concatFlagAndArgs = true; @@ -4665,7 +4670,7 @@ std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper( "CMAKE_" + language + (this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG" : "_LINKER_WRAPPER_FLAG"))); - std::vector<std::string> wrapperFlag = cmExpandedList(wrapper); + cmList wrapperFlag{ wrapper }; const std::string wrapperSep(this->Makefile->GetSafeDefinition( "CMAKE_" + language + (this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG_SEP" @@ -4863,10 +4868,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr, nullptr); - std::vector<std::string> debugProperties; - this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES", - debugProperties); - + cmList debugProperties{ this->Makefile->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugDirectories = !this->DebugLinkDirectoriesDone && cm::contains(debugProperties, "LINK_DIRECTORIES"); @@ -4911,7 +4914,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( EvaluatedTargetPropertyEntries entries; if (cmValue linkDepends = this->GetProperty("LINK_DEPENDS")) { - std::vector<std::string> depends = cmExpandedList(*linkDepends); + cmList depends{ *linkDepends }; for (const auto& depend : depends) { std::unique_ptr<TargetPropertyEntry> entry = CreateTargetPropertyEntry( *this->LocalGenerator->GetCMakeInstance(), depend); @@ -5590,8 +5593,8 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process public headers to mark the source files. if (cmValue files = this->GetProperty("PUBLIC_HEADER")) { - std::vector<std::string> relFiles = cmExpandedList(*files); - for (std::string const& relFile : relFiles) { + cmList relFiles{ *files }; + for (auto const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; flags.MacFolder = "Headers"; @@ -5603,8 +5606,8 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process private headers after public headers so that they take // precedence if a file is listed in both. if (cmValue files = this->GetProperty("PRIVATE_HEADER")) { - std::vector<std::string> relFiles = cmExpandedList(*files); - for (std::string const& relFile : relFiles) { + cmList relFiles{ *files }; + for (auto const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; flags.MacFolder = "PrivateHeaders"; @@ -5615,8 +5618,8 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Mark sources listed as resources. if (cmValue files = this->GetProperty("RESOURCE")) { - std::vector<std::string> relFiles = cmExpandedList(*files); - for (std::string const& relFile : relFiles) { + cmList relFiles{ *files }; + for (auto const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; flags.MacFolder = ""; @@ -5643,8 +5646,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const for (cmGeneratorTarget const* li : deps) { #define CM_READ_COMPATIBLE_INTERFACE(X, x) \ if (cmValue prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \ - std::vector<std::string> props; \ - cmExpandList(*prop, props); \ + cmList props(*prop); \ compat.Props##x.insert(props.begin(), props.end()); \ } CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) @@ -5757,7 +5759,7 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, return; } - std::vector<std::string> props = cmExpandedList(*prop); + cmList props{ *prop }; std::string pdir = cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/"); @@ -6718,10 +6720,8 @@ void cmGeneratorTarget::ReportPropertyOrigin( const std::string& p, const std::string& result, const std::string& report, const std::string& compatibilityType) const { - std::vector<std::string> debugProperties; - this->Target->GetMakefile()->GetDefExpandList( - "CMAKE_DEBUG_TARGET_PROPERTIES", debugProperties); - + cmList debugProperties{ this->Target->GetMakefile()->GetDefinition( + "CMAKE_DEBUG_TARGET_PROPERTIES") }; bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] && cm::contains(debugProperties, p); @@ -6800,10 +6800,10 @@ void cmGeneratorTarget::ExpandLinkItems( entry.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(entry.Value); cge->SetEvaluateForBuildsystem(true); - std::vector<std::string> libs = cmExpandedList( - cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, - this, headTarget->LinkerLanguage)); - for (std::string const& lib : libs) { + cmList libs{ cge->Evaluate(this->LocalGenerator, config, headTarget, + &dagChecker, this, + headTarget->LinkerLanguage) }; + for (auto const& lib : libs) { if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem( lib, cge->GetBacktrace(), &scope, field == LinkInterfaceField::Libraries ? LookupSelf::No @@ -7467,10 +7467,10 @@ std::vector<ValueType> computeImplicitLanguageTargets( currentTarget->GetRuntimeLinkLibrary(lang, config); if (cmValue runtimeLinkOptions = currentTarget->Makefile->GetDefinition( "CMAKE_" + lang + "_RUNTIME_LIBRARIES_" + runtimeLibrary)) { - std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions); - result.reserve(libsVec.size()); + cmList libsList{ *runtimeLinkOptions }; + result.reserve(libsList.size()); - for (std::string const& i : libsVec) { + for (auto const& i : libsList) { cmGeneratorTarget::TargetOrString resolved = currentTarget->ResolveTargetReference(i, lg); if (resolved.Target) { @@ -7551,9 +7551,9 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( this->ExpandLinkItems(info->LibrariesProp, cmMakeRange(info->Libraries), config, headTarget, interfaceFor, LinkInterfaceField::Libraries, iface); - std::vector<std::string> deps = cmExpandedList(info->SharedDeps); + cmList deps{ info->SharedDeps }; LookupLinkItemScope scope{ this->LocalGenerator }; - for (std::string const& dep : deps) { + for (auto const& dep : deps) { if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem( dep, cmListFileBacktrace(), &scope, LookupSelf::No)) { iface.SharedDeps.emplace_back(std::move(*maybeItem)); @@ -7874,8 +7874,8 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026( // behavior of CMP0024 and CMP0026 only. cmBTStringRange rng = this->Target->GetSourceEntries(); for (auto const& entry : rng) { - std::vector<std::string> files = cmExpandedList(entry.Value); - for (std::string const& li : files) { + cmList files{ entry.Value }; + for (auto const& li : files) { if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') { std::string objLibName = li.substr(17, li.size() - 18); @@ -8223,7 +8223,6 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries(); // Collect libraries directly linked in this configuration. for (auto const& entry : entryRange) { - std::vector<std::string> llibs; // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); @@ -8251,7 +8250,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr, this->LinkerLanguage); bool const checkCMP0027 = evaluated != entry.Value; - cmExpandList(evaluated, llibs); + cmList llibs(evaluated); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; } @@ -8262,7 +8261,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( impl.HadLinkLanguageSensitiveCondition = true; } - for (std::string const& lib : llibs) { + for (auto const& lib : llibs) { if (this->IsLinkLookupScope(lib, lg)) { continue; } @@ -8430,16 +8429,16 @@ bool cmGeneratorTarget::HasPackageReferences() const std::vector<std::string> cmGeneratorTarget::GetPackageReferences() const { - std::vector<std::string> packageReferences; + cmList packageReferences; if (this->IsInBuildSystem()) { if (cmValue vsPackageReferences = this->GetProperty("VS_PACKAGE_REFERENCES")) { - cmExpandList(*vsPackageReferences, packageReferences); + packageReferences.assign(*vsPackageReferences); } } - return packageReferences; + return std::move(packageReferences.data()); } std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const @@ -8544,6 +8543,30 @@ bool cmGeneratorTarget::IsLinkable() const this->IsExecutableWithExports()); } +bool cmGeneratorTarget::HasLinkDependencyFile(std::string const& config) const +{ + if (this->GetType() != cmStateEnums::EXECUTABLE && + this->GetType() != cmStateEnums::SHARED_LIBRARY && + this->GetType() != cmStateEnums::MODULE_LIBRARY) { + return false; + } + + if (this->Target->GetProperty("LINK_DEPENDS_NO_SHARED").IsOn()) { + // Do not use the linker dependency file because it includes shared + // libraries as well + return false; + } + + const std::string depsUseLinker{ "CMAKE_LINK_DEPENDS_USE_LINKER" }; + auto linkLanguage = this->GetLinkerLanguage(config); + const std::string langDepsUseLinker{ cmStrCat("CMAKE_", linkLanguage, + "_LINK_DEPENDS_USE_LINKER") }; + + return (!this->Makefile->IsDefinitionSet(depsUseLinker) || + this->Makefile->IsOn(depsUseLinker)) && + this->Makefile->IsOn(langDepsUseLinker); +} + bool cmGeneratorTarget::IsFrameworkOnApple() const { return this->Target->IsFrameworkOnApple(); @@ -8638,7 +8661,7 @@ bool cmGeneratorTarget::AddHeaderSetVerification() const bool all = verifyValue.IsEmpty(); std::set<std::string> verifySet; if (!all) { - auto verifyList = cmExpandedList(verifyValue); + cmList verifyList{ verifyValue }; verifySet.insert(verifyList.begin(), verifyList.end()); } @@ -8651,7 +8674,7 @@ bool cmGeneratorTarget::AddHeaderSetVerification() std::set<cmFileSet*> fileSets; for (auto const& entry : interfaceFileSetEntries) { - for (auto const& name : cmExpandedList(entry.Value)) { + for (auto const& name : cmList{ entry.Value }) { if (all || verifySet.count(name)) { fileSets.insert(this->Target->GetFileSet(name)); verifySet.erase(name); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 87227fd29c..78945c3fa9 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -805,6 +805,9 @@ public: /** Return whether this target may be used to link another target. */ bool IsLinkable() const; + /** Return whether the link step generates a dependency file. */ + bool HasLinkDependencyFile(std::string const& config) const; + /** Return whether this target is a shared library Framework on Apple. */ bool IsFrameworkOnApple() const; @@ -912,6 +915,8 @@ public: std::vector<std::string> GetGeneratedISPCObjects( std::string const& config) const; + void AddSystemIncludeDirectory(std::string const& inc, + std::string const& lang); bool AddHeaderSetVerification(); std::string GenerateHeaderSetVerificationFile( cmSourceFile& source, const std::string& dir, diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 8471dfe615..a1e0650d20 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGhsMultiGenerator.h" #include "cmLinkLineComputer.h" // IWYU pragma: keep +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" @@ -484,7 +485,7 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty( { cmValue prop = sf->GetProperty(propName); if (prop) { - std::vector<std::string> list = cmExpandedList(*prop); + cmList list{ *prop }; for (const std::string& p : list) { fout << " " << propFlag << p << '\n'; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 3563a1a17d..040f500519 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -42,6 +42,7 @@ #include "cmInstallGenerator.h" #include "cmInstallRuntimeDependencySet.h" #include "cmLinkLineComputer.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMSVC60LinkLineComputer.h" #include "cmMakefile.h" @@ -238,10 +239,10 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp); // Split compiler from arguments - std::vector<std::string> cnameArgVec; + cmList cnameArgList; if (cname && !cname->empty()) { - cmExpandList(*cname, cnameArgVec); - cname = cmValue(cnameArgVec.front()); + cnameArgList.assign(*cname); + cname = cmValue(cnameArgList.front()); } std::string changeVars; @@ -670,7 +671,7 @@ void cmGlobalGenerator::EnableLanguage( mf->GetState()->SetInTopLevelIncludes(true); std::string includes = mf->GetSafeDefinition("CMAKE_PROJECT_TOP_LEVEL_INCLUDES"); - std::vector<std::string> includesList = cmExpandedList(includes); + cmList includesList{ includes }; for (std::string const& setupFile : includesList) { std::string absSetupFile = cmSystemTools::CollapseFullPath( setupFile, mf->GetCurrentSourceDirectory()); @@ -1234,7 +1235,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, std::string ignoreExtensionsVar = std::string("CMAKE_") + std::string(l) + std::string("_IGNORE_EXTENSIONS"); std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar); - std::vector<std::string> extensionList = cmExpandedList(ignoreExts); + cmList extensionList{ ignoreExts }; for (std::string const& i : extensionList) { this->IgnoreExtensions[i] = true; } @@ -1246,7 +1247,7 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, std::string extensionsVar = std::string("CMAKE_") + std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS"); const std::string& exts = mf->GetSafeDefinition(extensionsVar); - std::vector<std::string> extensionList = cmExpandedList(exts); + cmList extensionList{ exts }; for (std::string const& i : extensionList) { this->ExtensionToLanguage[i] = l; } @@ -1887,10 +1888,9 @@ void cmGlobalGenerator::FinalizeTargetConfiguration() "CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES"; std::string const& standardIncludesStr = mf->GetSafeDefinition(standardIncludesVar); - std::vector<std::string> standardIncludesVec = - cmExpandedList(standardIncludesStr); - standardIncludesSet.insert(standardIncludesVec.begin(), - standardIncludesVec.end()); + cmList standardIncludesList{ standardIncludesStr }; + standardIncludesSet.insert(standardIncludesList.begin(), + standardIncludesList.end()); } mf->AddSystemIncludeDirectories(standardIncludesSet); } @@ -1985,7 +1985,6 @@ void cmGlobalGenerator::CheckTargetProperties() notFoundMap[varName] = text; } } - std::vector<std::string> incs; cmValue incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); if (!incDirProp) { continue; @@ -1994,7 +1993,7 @@ void cmGlobalGenerator::CheckTargetProperties() std::string incDirs = cmGeneratorExpression::Preprocess( *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); - cmExpandList(incDirs, incs); + cmList incs(incDirs); for (std::string const& incDir : incs) { if (incDir.size() > 9 && cmIsNOTFOUND(incDir)) { @@ -2789,11 +2788,9 @@ void cmGlobalGenerator::AddGlobalTarget_Test( cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCTestCommand()); singleLine.push_back("--force-new-ctest-process"); - std::vector<std::string> args; - if (mf->GetDefExpandList("CMAKE_CTEST_ARGUMENTS", args)) { - for (auto const& arg : args) { - singleLine.push_back(arg); - } + cmList args(mf->GetDefinition("CMAKE_CTEST_ARGUMENTS")); + for (auto const& arg : args) { + singleLine.push_back(arg); } if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') { singleLine.push_back("-C"); @@ -3348,12 +3345,12 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) cmSystemTools::MakeDirectory(dir); cmGeneratedFileStream fout(file); - std::vector<std::string> labels; + cmList labels; // List the target-wide labels. All sources in the target get // these labels. if (targetLabels) { - cmExpandList(*targetLabels, labels); + labels.assign(*targetLabels); if (!labels.empty()) { fout << "# Target labels\n"; for (std::string const& l : labels) { @@ -3364,27 +3361,27 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) } // List directory labels - std::vector<std::string> directoryLabelsList; - std::vector<std::string> cmakeDirectoryLabelsList; + cmList directoryLabelsList; + cmList cmakeDirectoryLabelsList; if (directoryLabels) { - cmExpandList(*directoryLabels, directoryLabelsList); + directoryLabelsList.assign(*directoryLabels); } if (cmakeDirectoryLabels) { - cmExpandList(*cmakeDirectoryLabels, cmakeDirectoryLabelsList); + cmakeDirectoryLabelsList.assign(*cmakeDirectoryLabels); } if (!directoryLabelsList.empty() || !cmakeDirectoryLabelsList.empty()) { fout << "# Directory labels\n"; } - for (std::string const& li : directoryLabelsList) { + for (auto const& li : directoryLabelsList) { fout << " " << li << "\n"; lj_target_labels.append(li); } - for (std::string const& li : cmakeDirectoryLabelsList) { + for (auto const& li : cmakeDirectoryLabelsList) { fout << " " << li << "\n"; lj_target_labels.append(li); } @@ -3405,10 +3402,9 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) fout << sfp << "\n"; lj_source["file"] = sfp; if (cmValue svalue = sf->GetProperty("LABELS")) { - labels.clear(); Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue; - cmExpandList(*svalue, labels); - for (std::string const& label : labels) { + labels.assign(*svalue); + for (auto const& label : labels) { fout << " " << label << "\n"; lj_source_labels.append(label); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index dde364886e..79fe52c193 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -546,6 +546,8 @@ public: return cm::nullopt; } + virtual bool SupportsLinkerDependencyFile() const { return false; } + std::string GetSharedLibFlagsForLanguage(std::string const& lang) const; /** Generate an <output>.rule file path for a given command output. */ diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index b1f2b4a393..578e805332 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -18,6 +18,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGhsMultiGpj.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" @@ -531,7 +532,7 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, fout << "macro PROJ_NAME=" << root->GetProjectName() << '\n'; cmValue ghsGpjMacros = root->GetMakefile()->GetDefinition("GHS_GPJ_MACROS"); if (ghsGpjMacros) { - std::vector<std::string> expandedList = cmExpandedList(*ghsGpjMacros); + cmList expandedList{ *ghsGpjMacros }; for (std::string const& arg : expandedList) { fout << "macro " << arg << '\n'; } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 0c28776a82..84c85e07e6 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -32,6 +32,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkLineComputer.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" @@ -3031,19 +3032,17 @@ void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs( bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables() { - std::vector<std::string> configsVec; - cmExpandList( - this->Makefiles.front()->GetSafeDefinition("CMAKE_CONFIGURATION_TYPES"), - configsVec); - if (configsVec.empty()) { - configsVec.emplace_back(); + cmList configsList{ this->Makefiles.front()->GetDefinition( + "CMAKE_CONFIGURATION_TYPES") }; + if (configsList.empty()) { + configsList.emplace_back(); } - std::set<std::string> configs(configsVec.cbegin(), configsVec.cend()); + std::set<std::string> configs(configsList.cbegin(), configsList.cend()); this->DefaultFileConfig = this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_BUILD_TYPE"); if (this->DefaultFileConfig.empty()) { - this->DefaultFileConfig = configsVec.front(); + this->DefaultFileConfig = configsList.front(); } if (!configs.count(this->DefaultFileConfig)) { std::ostringstream msg; @@ -3055,11 +3054,9 @@ bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables() return false; } - std::vector<std::string> crossConfigsVec; - cmExpandList( - this->Makefiles.front()->GetSafeDefinition("CMAKE_CROSS_CONFIGS"), - crossConfigsVec); - auto crossConfigs = ListSubsetWithAll(configs, configs, crossConfigsVec); + cmList crossConfigsList{ this->Makefiles.front()->GetSafeDefinition( + "CMAKE_CROSS_CONFIGS") }; + auto crossConfigs = ListSubsetWithAll(configs, configs, crossConfigsList); if (!crossConfigs) { std::ostringstream msg; msg << "CMAKE_CROSS_CONFIGS is not a subset of " @@ -3086,12 +3083,11 @@ bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables() return false; } - std::vector<std::string> defaultConfigsVec; - cmExpandList(defaultConfigsString, defaultConfigsVec); + cmList defaultConfigsList(defaultConfigsString); if (!this->DefaultFileConfig.empty()) { auto defaultConfigs = ListSubsetWithAll(this->GetCrossConfigs(this->DefaultFileConfig), - this->CrossConfigs, defaultConfigsVec); + this->CrossConfigs, defaultConfigsList); if (!defaultConfigs) { std::ostringstream msg; msg << "CMAKE_DEFAULT_CONFIGS is not a subset of CMAKE_CROSS_CONFIGS"; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index bd541685c9..bfbe57f22b 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -236,6 +236,8 @@ public: return cmDepfileFormat::GccDepfile; } + bool SupportsLinkerDependencyFile() const override { return true; } + virtual cmGeneratedFileStream* GetImplFileStream( const std::string& /*config*/) const { diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 214ba2af51..760679a051 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -99,6 +99,12 @@ public: */ bool SupportsCustomCommandDepfile() const override { return true; } + /** + * Utilized to determine if this generator + * supports linker dependency file. + */ + bool SupportsLinkerDependencyFile() const override { return true; } + /** Get the documentation entry for this generator. */ static cmDocumentationEntry GetDocumentation(); diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index de139241ed..bcb26cc1cb 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalVisualStudioGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -205,12 +206,12 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations( !platformMapping.empty() ? platformMapping : this->GetPlatformName(); std::string guid = this->GetGUID(name); for (std::string const& i : configs) { - std::vector<std::string> mapConfig; + cmList mapConfig; const char* dstConfig = i.c_str(); if (target.GetProperty("EXTERNAL_MSPROJECT")) { if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" + cmSystemTools::UpperCase(i))) { - cmExpandList(*m, mapConfig); + mapConfig.assign(*m); if (!mapConfig.empty()) { dstConfig = mapConfig[0].c_str(); } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 5de3a55939..694698e559 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" @@ -580,7 +581,7 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( } fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; cmValue p = root->GetMakefile()->GetProperty(it); - std::vector<std::string> keyValuePairs = cmExpandedList(p ? *p : ""); + cmList keyValuePairs{ *p }; for (std::string const& itPair : keyValuePairs) { const std::string::size_type posEqual = itPair.find('='); if (posEqual != std::string::npos) { diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 2aba46fe2c..819bb09b1a 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -20,6 +20,7 @@ #include "cmGlobalGenerator.h" #include "cmGlobalVisualStudio7Generator.h" #include "cmGlobalVisualStudioGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalVisualStudio7Generator.h" @@ -262,6 +263,33 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() cmTarget* tgt = lg.AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, std::move(cc)); + // Collect the input files used to generate all targets in this + // project. + std::vector<std::string> listFiles; + for (const auto& gen : generators) { + cm::append(listFiles, gen->GetMakefile()->GetListFiles()); + } + // Sort the list of input files and remove duplicates. + std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); + auto new_end = std::unique(listFiles.begin(), listFiles.end()); + listFiles.erase(new_end, listFiles.end()); + + // Add all cmake input files which are used by the project + // so Visual Studio does not close them when reloading it. + for (const std::string& listFile : listFiles) { + if (listFile.find("/CMakeFiles/") != std::string::npos) { + continue; + } + if (!cmSystemTools::IsSubDirectory(listFile, + lg.GetMakefile()->GetHomeDirectory()) && + !cmSystemTools::IsSubDirectory( + listFile, lg.GetMakefile()->GetHomeOutputDirectory())) { + continue; + } + + tgt->AddSource(listFile); + } + auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg); auto* gt = ptr.get(); lg.AddGeneratorTarget(std::move(ptr)); @@ -295,13 +323,6 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // The custom rule runs cmake so set UTF-8 pipes. bool stdPipesUTF8 = true; - // Collect the input files used to generate all targets in this - // project. - std::vector<std::string> listFiles; - for (const auto& gen : generators) { - cm::append(listFiles, gen->GetMakefile()->GetListFiles()); - } - // Add a custom prebuild target to run the VerifyGlobs script. cmake* cm = this->GetCMakeInstance(); if (cm->DoWriteGlobVerifyTarget()) { @@ -325,11 +346,6 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() listFiles.push_back(cm->GetGlobVerifyStamp()); } - // Sort the list of input files and remove duplicates. - std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); - auto new_end = std::unique(listFiles.begin(), listFiles.end()); - listFiles.erase(new_end, listFiles.end()); - // Create a rule to re-run CMake. std::string argS = cmStrCat("-S", lg.GetSourceDirectory()); std::string argB = cmStrCat("-B", lg.GetBinaryDirectory()); @@ -396,12 +412,12 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( { std::string guid = this->GetGUID(name); for (std::string const& i : configs) { - std::vector<std::string> mapConfig; + cmList mapConfig; const char* dstConfig = i.c_str(); if (target.GetProperty("EXTERNAL_MSPROJECT")) { if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" + cmSystemTools::UpperCase(i))) { - cmExpandList(*m, mapConfig); + mapConfig.assign(*m); if (!mapConfig.empty()) { dstConfig = mapConfig[0].c_str(); } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 139635797f..60f46e5aca 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -30,6 +30,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGeneratorFactory.h" #include "cmLinkItem.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalXCodeGenerator.h" @@ -1027,7 +1028,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( cmValue extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES"); if (extraFileAttributes) { // Expand the list of attributes. - std::vector<std::string> attributes = cmExpandedList(*extraFileAttributes); + cmList attributes{ *extraFileAttributes }; // Store the attributes. for (const auto& attribute : attributes) { @@ -1171,7 +1172,7 @@ template <class T> std::string GetTargetObjectDirArch(T const& target, const std::string& defaultVal) { - auto archs = cmExpandedList(target.GetSafeProperty("OSX_ARCHITECTURES")); + cmList archs{ target.GetSafeProperty("OSX_ARCHITECTURES") }; if (archs.size() > 1) { return "$(CURRENT_ARCH)"; } else if (archs.size() == 1) { @@ -3127,8 +3128,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, cmGeneratorTarget* gtgt) { - std::vector<std::string> const configVector = cmExpandedList( - this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES")); + cmList const configList{ this->CurrentMakefile->GetRequiredDefinition( + "CMAKE_CONFIGURATION_TYPES") }; cmXCodeObject* configlist = this->CreateObject(cmXCodeObject::XCConfigurationList); cmXCodeObject* buildConfigurations = @@ -3140,7 +3141,7 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, configlist->SetComment(comment); target->AddAttribute("buildConfigurationList", this->CreateObjectReference(configlist)); - for (auto const& i : configVector) { + for (auto const& i : configList) { cmXCodeObject* config = this->CreateObject(cmXCodeObject::XCBuildConfiguration); buildConfigurations->AddObject(config); @@ -3153,12 +3154,12 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, this->CreateTargetXCConfigSettings(gtgt, config, i); } - if (!configVector.empty()) { + if (!configList.empty()) { configlist->AddAttribute("defaultConfigurationName", - this->CreateString(configVector[0])); + this->CreateString(configList[0])); configlist->AddAttribute("defaultConfigurationIsVisible", this->CreateString("0")); - return configVector[0]; + return configList[0]; } return ""; } @@ -4029,7 +4030,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects( this->CreateString("0")); cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); // Collect all embedded frameworks and dylibs and add them to build phase - std::vector<std::string> relFiles = cmExpandedList(*files); + cmList relFiles{ *files }; for (std::string const& relFile : relFiles) { cmXCodeObject* buildFile{ nullptr }; std::string filePath = relFile; @@ -4599,13 +4600,12 @@ std::string cmGlobalXCodeGenerator::GetTargetTempDir( void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) { this->Architectures.clear(); - cmValue sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); - if (sysroot) { - mf->GetDefExpandList("CMAKE_OSX_ARCHITECTURES", this->Architectures); - } + cmList::append(this->Architectures, + mf->GetDefinition("CMAKE_OSX_ARCHITECTURES")); if (this->Architectures.empty()) { - mf->GetDefExpandList("_CMAKE_APPLE_ARCHS_DEFAULT", this->Architectures); + cmList::append(this->Architectures, + mf->GetDefinition("_CMAKE_APPLE_ARCHS_DEFAULT")); } if (this->Architectures.empty()) { @@ -5008,7 +5008,7 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs, } // Expand the list of definitions. - std::vector<std::string> defines = cmExpandedList(defines_list); + cmList defines{ defines_list }; // Store the definitions in the string. this->AppendDefines(defs, defines, dflag); diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 2bb438d7d4..a8a7abb087 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -15,6 +15,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" @@ -255,9 +256,8 @@ void cmGraphVizWriter::ReadSettings( this->TargetsToIgnoreRegex.clear(); if (!ignoreTargetsRegexes.empty()) { - std::vector<std::string> ignoreTargetsRegExVector = - cmExpandedList(ignoreTargetsRegexes); - for (std::string const& currentRegexString : ignoreTargetsRegExVector) { + cmList ignoreTargetsRegExList{ ignoreTargetsRegexes }; + for (std::string const& currentRegexString : ignoreTargetsRegExList) { cmsys::RegularExpression currentRegex; if (!currentRegex.compile(currentRegexString)) { std::cerr << "Could not compile bad regex \"" << currentRegexString diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 9468d4abdb..f94faf88b8 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -12,6 +12,7 @@ #include "cmsys/String.h" #include "cmIDEFlagTable.h" +#include "cmList.h" #include "cmStringAlgorithms.h" cmIDEOptions::cmIDEOptions() diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 40230d9fb6..7f5f15b3c9 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -39,6 +39,7 @@ #include "cmInstallRuntimeDependencySetGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -1079,7 +1080,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) { cmValue files = target.GetProperty("PRIVATE_HEADER"); if (cmNonempty(files)) { - std::vector<std::string> relFiles = cmExpandedList(*files); + cmList relFiles{ *files }; std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) { return false; @@ -1101,7 +1102,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, files = target.GetProperty("PUBLIC_HEADER"); if (cmNonempty(files)) { - std::vector<std::string> relFiles = cmExpandedList(*files); + cmList relFiles{ *files }; std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) { return false; @@ -1123,7 +1124,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, files = target.GetProperty("RESOURCE"); if (cmNonempty(files)) { - std::vector<std::string> relFiles = cmExpandedList(*files); + cmList relFiles{ *files }; std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) { return false; @@ -1145,8 +1146,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (!namelinkOnly) { for (std::size_t i = 0; i < fileSetArgs.size(); i++) { if (auto* fileSet = target.GetFileSet(fileSetArgs[i].GetFileSet())) { - auto interfaceFileSetEntries = cmExpandedList(target.GetSafeProperty( - cmTarget::GetInterfaceFileSetsPropertyName(fileSet->GetType()))); + cmList interfaceFileSetEntries{ target.GetSafeProperty( + cmTarget::GetInterfaceFileSetsPropertyName(fileSet->GetType())) }; if (std::find(interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(), fileSetArgs[i].GetFileSet()) != diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index d358763c71..6aa99102bd 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorExpression.h" #include "cmInstallType.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -53,17 +54,16 @@ bool cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg) std::vector<std::string> cmInstallDirectoryGenerator::GetDirectories( std::string const& config) const { - std::vector<std::string> directories; + cmList directories; if (this->ActionsPerConfig) { for (std::string const& f : this->Directories) { - cmExpandList( - cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config), - directories); + directories.append( + cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config)); } } else { directories = this->Directories; } - return directories; + return std::move(directories.data()); } void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os, diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 18a852b210..43dc656a75 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -6,8 +6,8 @@ #include "cmGeneratorExpression.h" #include "cmInstallType.h" +#include "cmList.h" #include "cmListFileCache.h" -#include "cmStringAlgorithms.h" class cmLocalGenerator; @@ -69,17 +69,15 @@ std::string cmInstallFilesGenerator::GetRename(std::string const& config) const std::vector<std::string> cmInstallFilesGenerator::GetFiles( std::string const& config) const { - std::vector<std::string> files; if (this->ActionsPerConfig) { + cmList files; for (std::string const& f : this->Files) { - cmExpandList( - cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config), - files); + files.append( + cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config)); } - } else { - files = this->Files; + return std::move(files.data()); } - return files; + return this->Files; } void cmInstallFilesGenerator::AddFilesInstallRule( diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 5bf8320bbb..381c91bac1 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -5,9 +5,9 @@ #include <utility> #include "cmGeneratorExpression.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" -#include "cmStringAlgorithms.h" #include "cmValue.h" cmInstalledFile::cmInstalledFile() = default; @@ -97,12 +97,11 @@ bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const return isSet && cmIsOn(value); } -void cmInstalledFile::GetPropertyAsList(const std::string& prop, - std::vector<std::string>& list) const +std::vector<std::string> cmInstalledFile::GetPropertyAsList( + const std::string& prop) const { std::string value; this->GetProperty(prop, value); - list.clear(); - cmExpandList(value, list); + return std::move(cmList(value).data()); } diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index 82474f5203..373c34938a 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -59,8 +59,7 @@ public: bool GetPropertyAsBool(const std::string& prop) const; - void GetPropertyAsList(const std::string& prop, - std::vector<std::string>& list) const; + std::vector<std::string> GetPropertyAsList(const std::string& prop) const; void SetName(cmMakefile* mf, const std::string& name); diff --git a/Source/cmLDConfigLDConfigTool.cxx b/Source/cmLDConfigLDConfigTool.cxx index cce6178dae..0752b3353d 100644 --- a/Source/cmLDConfigLDConfigTool.cxx +++ b/Source/cmLDConfigLDConfigTool.cxx @@ -9,9 +9,9 @@ #include "cmsys/RegularExpression.hxx" +#include "cmList.h" #include "cmMakefile.h" #include "cmRuntimeDependencyArchive.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUVProcessChain.h" @@ -34,7 +34,7 @@ bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths) } } - std::vector<std::string> ldConfigCommand = cmExpandedList(ldConfigPath); + cmList ldConfigCommand{ ldConfigPath }; ldConfigCommand.emplace_back("-v"); ldConfigCommand.emplace_back("-N"); // Don't rebuild the cache. ldConfigCommand.emplace_back("-X"); // Don't update links. diff --git a/Source/cmList.cxx b/Source/cmList.cxx index bf5a65459a..022fcd2b4c 100644 --- a/Source/cmList.cxx +++ b/Source/cmList.cxx @@ -287,18 +287,20 @@ protected: : TransformSelector(std::move(tag)) { } - TransformSelectorIndexes(std::string&& tag, std::vector<int> const& indexes) + TransformSelectorIndexes(std::string&& tag, + std::vector<index_type> const& indexes) : TransformSelector(std::move(tag)) , Indexes(indexes) { } - TransformSelectorIndexes(std::string&& tag, std::vector<int>&& indexes) + TransformSelectorIndexes(std::string&& tag, + std::vector<index_type>&& indexes) : TransformSelector(std::move(tag)) , Indexes(indexes) { } - int NormalizeIndex(index_type index, std::size_t count) + index_type NormalizeIndex(index_type index, std::size_t count) { if (index < 0) { index = static_cast<index_type>(count) + index; @@ -338,7 +340,7 @@ public: class TransformSelectorFor : public TransformSelectorIndexes { public: - TransformSelectorFor(int start, int stop, int step) + TransformSelectorFor(index_type start, index_type stop, index_type step) : TransformSelectorIndexes("FOR") , Start(start) , Stop(stop) @@ -369,7 +371,7 @@ public: auto start = this->Start; auto step = this->Step; std::generate(this->Indexes.begin(), this->Indexes.end(), - [&start, step]() -> int { + [&start, step]() -> index_type { auto r = start; start += step; return r; @@ -805,7 +807,7 @@ std::string cmList::join(cm::string_view glue) const return cmJoin(this->Values, glue); } -std::string& cmList::append(cm::string_view value, std::string& list) +std::string& cmList::append(std::string& list, cm::string_view value) { if (list.empty()) { list = std::string(value); @@ -816,7 +818,7 @@ std::string& cmList::append(cm::string_view value, std::string& list) return list; } -std::string& cmList::prepend(cm::string_view value, std::string& list) +std::string& cmList::prepend(std::string& list, cm::string_view value) { if (list.empty()) { list = std::string(value); @@ -835,18 +837,19 @@ cmList::size_type cmList::ComputeIndex(index_type pos, bool boundCheck) const cmStrCat("index: ", pos, " out of range (0, 0)")); } + auto index = pos; if (!this->Values.empty()) { auto length = this->Values.size(); - if (pos < 0) { - pos = static_cast<index_type>(length) + pos; + if (index < 0) { + index = static_cast<index_type>(length) + index; } - if (pos < 0 || length <= static_cast<size_type>(pos)) { + if (index < 0 || length <= static_cast<size_type>(index)) { throw std::out_of_range(cmStrCat("index: ", pos, " out of range (-", this->Values.size(), ", ", this->Values.size() - 1, ")")); } } - return pos; + return index; } return pos < 0 ? this->Values.size() + pos : pos; @@ -860,18 +863,19 @@ cmList::size_type cmList::ComputeInsertIndex(index_type pos, cmStrCat("index: ", pos, " out of range (0, 0)")); } + auto index = pos; if (!this->Values.empty()) { auto length = this->Values.size(); - if (pos < 0) { - pos = static_cast<index_type>(length) + pos; + if (index < 0) { + index = static_cast<index_type>(length) + index; } - if (pos < 0 || length < static_cast<size_type>(pos)) { + if (index < 0 || length < static_cast<size_type>(index)) { throw std::out_of_range(cmStrCat("index: ", pos, " out of range (-", this->Values.size(), ", ", this->Values.size(), ")")); } } - return pos; + return index; } return pos < 0 ? this->Values.size() + pos : pos; @@ -882,7 +886,7 @@ cmList cmList::GetItems(std::vector<index_type>&& indexes) const cmList listItems; for (auto index : indexes) { - listItems.emplace_back(this->at(index)); + listItems.emplace_back(this->get_item(index)); } return listItems; @@ -896,9 +900,10 @@ cmList& cmList::RemoveItems(std::vector<index_type>&& indexes) // compute all indexes std::vector<size_type> idx(indexes.size()); - std::transform( - indexes.cbegin(), indexes.cend(), idx.begin(), - [this](const index_type& index) { return this->ComputeIndex(index); }); + std::transform(indexes.cbegin(), indexes.cend(), idx.begin(), + [this](const index_type& index) -> size_type { + return this->ComputeIndex(index); + }); std::sort(idx.begin(), idx.end(), [](size_type l, size_type r) { return l > r; }); @@ -925,8 +930,8 @@ cmList& cmList::RemoveItems(std::vector<std::string>&& items) } cmList::container_type::iterator cmList::Insert( - container_type::const_iterator pos, std::string&& value, - container_type& container, ExpandElements expandElements, + container_type& container, container_type::const_iterator pos, + std::string&& value, ExpandElements expandElements, EmptyElements emptyElements) { auto delta = std::distance(container.cbegin(), pos); diff --git a/Source/cmList.h b/Source/cmList.h index d994ad3890..d9ce9510c6 100644 --- a/Source/cmList.h +++ b/Source/cmList.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <algorithm> +#include <cstdint> #include <initializer_list> #include <iterator> #include <memory> @@ -16,19 +17,25 @@ #include <vector> #include <cm/string_view> +#include <cm/type_traits> +#include <cmext/iterator> #include "cmValue.h" /** * CMake lists management + * A CMake list is a string where list elements are separated by the ';' + * character. * * For all operations, input arguments (single value like cm::string_view or * multiple values specified through pair of iterators) are, by default, * expanded. The expansion can be controlled by the cmList::ExpandElements * option. * - * There is an exception to this rule. The following methods do not expand - * their argument: cmList::push_back, cmList::emplace and cmList::emplace_back. + * There ate some exceptions to this rule: + * * When the input argument is a cmList instance, the value is not expanded. + * * The following methods do not expand their argument: cmList::push_back, + * cmList::emplace and cmList::emplace_back. */ class cmList @@ -38,7 +45,7 @@ public: using value_type = container_type::value_type; using allocator_type = container_type::allocator_type; - using index_type = int; + using index_type = std::intptr_t; using size_type = container_type::size_type; using difference_type = container_type::difference_type; using reference = container_type::reference; @@ -74,8 +81,18 @@ public: this->assign(value, expandElements, emptyElements); } cmList(cm::string_view value, EmptyElements emptyElements) + : cmList(value, ExpandElements::Yes, emptyElements) + { + } + cmList(std::string const& value, + ExpandElements expandElements = ExpandElements::Yes, + EmptyElements emptyElements = EmptyElements::No) + { + this->assign(value, expandElements, emptyElements); + } + cmList(std::string const& value, EmptyElements emptyElements) + : cmList(value, ExpandElements::Yes, emptyElements) { - this->assign(value, ExpandElements::Yes, emptyElements); } cmList(cmValue list, ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) @@ -135,6 +152,11 @@ public: this->assign(value); return *this; } + cmList& operator=(std::string const& value) + { + this->assign(value); + return *this; + } cmList& operator=(cmValue value) { if (value) { @@ -175,6 +197,17 @@ public: { this->assign(value, ExpandElements::Yes, emptyElements); } + void assign(std::string const& value, + ExpandElements expandElements = ExpandElements::Yes, + EmptyElements emptyElements = EmptyElements::No) + { + this->clear(); + this->append(value, expandElements, emptyElements); + } + void assign(std::string const& value, EmptyElements emptyElements) + { + this->assign(value, ExpandElements::Yes, emptyElements); + } void assign(cmValue value, ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) @@ -204,17 +237,17 @@ public: this->assign(first, last, ExpandElements::Yes, emptyElements); } void assign(const cmList& init, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { this->assign(init.begin(), init.end(), expandElements, emptyElements); } void assign(const cmList& init, EmptyElements emptyElements) { - this->assign(init, ExpandElements::Yes, emptyElements); + this->assign(init, ExpandElements::No, emptyElements); } void assign(cmList&& init, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { this->assign(std::make_move_iterator(init.begin()), @@ -224,7 +257,7 @@ public: } void assign(cmList&& init, EmptyElements emptyElements) { - this->assign(std::move(init), ExpandElements::Yes, emptyElements); + this->assign(std::move(init), ExpandElements::No, emptyElements); } void assign(const container_type& init, ExpandElements expandElements = ExpandElements::Yes, @@ -265,24 +298,21 @@ public: operator container_type&&() && noexcept { return std::move(this->Values); } // Element access - reference at(index_type pos) + reference at(size_type pos) { return this->Values.at(pos); } + const_reference at(size_type pos) const { return this->Values.at(pos); } + + reference operator[](size_type pos) { return this->Values[pos]; } + const_reference operator[](size_type pos) const { return this->Values[pos]; } + + reference get_item(index_type pos) { return this->Values.at(this->ComputeIndex(pos)); } - const_reference at(index_type pos) const + const_reference get_item(index_type pos) const { return this->Values.at(this->ComputeIndex(pos)); } - reference operator[](index_type pos) - { - return this->Values[this->ComputeIndex(pos, false)]; - } - const_reference operator[](index_type pos) const - { - return this->Values[this->ComputeIndex(pos, false)]; - } - reference front() { return this->Values.front(); } const_reference front() const { return this->Values.front(); } @@ -361,7 +391,7 @@ public: ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) { - return cmList::Insert(pos, std::string(value), this->Values, + return cmList::Insert(this->Values, pos, std::string(value), expandElements, emptyElements); } iterator insert(const_iterator pos, cm::string_view value, @@ -369,6 +399,18 @@ public: { return this->insert(pos, value, ExpandElements::Yes, emptyElements); } + iterator insert(const_iterator pos, std::string const& value, + ExpandElements expandElements = ExpandElements::Yes, + EmptyElements emptyElements = EmptyElements::No) + { + return cmList::Insert(this->Values, pos, value, expandElements, + emptyElements); + } + iterator insert(const_iterator pos, std::string const& value, + EmptyElements emptyElements) + { + return this->insert(pos, value, ExpandElements::Yes, emptyElements); + } iterator insert(const_iterator pos, cmValue value, ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) @@ -390,7 +432,7 @@ public: ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) { - return cmList::Insert(pos, first, last, this->Values, expandElements, + return cmList::Insert(this->Values, pos, first, last, expandElements, emptyElements); } template <typename InputIterator> @@ -400,7 +442,7 @@ public: return this->insert(pos, first, last, ExpandElements::Yes, emptyElements); } iterator insert(const_iterator pos, const cmList& values, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { return this->insert(pos, values.begin(), values.end(), expandElements, @@ -409,10 +451,10 @@ public: iterator insert(const_iterator pos, const cmList& values, EmptyElements emptyElements) { - return this->insert(pos, values, ExpandElements::Yes, emptyElements); + return this->insert(pos, values, ExpandElements::No, emptyElements); } iterator insert(const_iterator pos, cmList&& values, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { auto result = this->insert(pos, std::make_move_iterator(values.begin()), @@ -425,7 +467,7 @@ public: iterator insert(const_iterator pos, cmList&& values, EmptyElements emptyElements) { - return this->insert(pos, std::move(values), ExpandElements::Yes, + return this->insert(pos, std::move(values), ExpandElements::No, emptyElements); } iterator insert(const_iterator pos, const container_type& values, @@ -472,6 +514,16 @@ public: { return this->append(value, ExpandElements::Yes, emptyElements); } + iterator append(std::string const& value, + ExpandElements expandElements = ExpandElements::Yes, + EmptyElements emptyElements = EmptyElements::No) + { + return this->insert(this->cend(), value, expandElements, emptyElements); + } + iterator append(std::string const& value, EmptyElements emptyElements) + { + return this->append(value, ExpandElements::Yes, emptyElements); + } iterator append(cmValue value, ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) @@ -501,7 +553,7 @@ public: return this->append(first, last, ExpandElements::Yes, emptyElements); } iterator append(const cmList& values, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { return this->append(values.begin(), values.end(), expandElements, @@ -509,10 +561,10 @@ public: } iterator append(const cmList& values, EmptyElements emptyElements) { - return this->append(values, ExpandElements::Yes, emptyElements); + return this->append(values, ExpandElements::No, emptyElements); } iterator append(cmList&& values, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { auto result = this->append(std::make_move_iterator(values.begin()), @@ -524,7 +576,7 @@ public: } iterator append(cmList&& values, EmptyElements emptyElements) { - return this->append(std::move(values), ExpandElements::Yes, emptyElements); + return this->append(std::move(values), ExpandElements::No, emptyElements); } iterator append(const container_type& values, ExpandElements expandElements = ExpandElements::Yes, @@ -567,6 +619,16 @@ public: { return this->prepend(value, ExpandElements::Yes, emptyElements); } + iterator prepend(std::string const& value, + ExpandElements expandElements = ExpandElements::Yes, + EmptyElements emptyElements = EmptyElements::No) + { + return this->insert(this->cbegin(), value, expandElements, emptyElements); + } + iterator prepend(std::string const& value, EmptyElements emptyElements) + { + return this->prepend(value, ExpandElements::Yes, emptyElements); + } iterator prepend(cmValue value, ExpandElements expandElements = ExpandElements::Yes, EmptyElements emptyElements = EmptyElements::No) @@ -596,7 +658,7 @@ public: return this->prepend(first, last, ExpandElements::Yes, emptyElements); } iterator prepend(const cmList& values, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { return this->prepend(values.begin(), values.end(), expandElements, @@ -604,10 +666,10 @@ public: } iterator prepend(const cmList& values, EmptyElements emptyElements) { - return this->prepend(values, ExpandElements::Yes, emptyElements); + return this->prepend(values, ExpandElements::No, emptyElements); } iterator prepend(cmList&& values, - ExpandElements expandElements = ExpandElements::Yes, + ExpandElements expandElements = ExpandElements::No, EmptyElements emptyElements = EmptyElements::No) { auto result = this->prepend(std::make_move_iterator(values.begin()), @@ -619,8 +681,7 @@ public: } iterator prepend(cmList&& values, EmptyElements emptyElements) { - return this->prepend(std::move(values), ExpandElements::Yes, - emptyElements); + return this->prepend(std::move(values), ExpandElements::No, emptyElements); } iterator prepend(const container_type& values, ExpandElements expandElements = ExpandElements::Yes, @@ -654,6 +715,7 @@ public: return this->insert(this->cbegin(), ilist); } + void push_back(std::string const& value) { this->Values.push_back(value); } void push_back(cm::string_view value) { this->Values.push_back(std::string{ value }); @@ -733,6 +795,8 @@ public: cmList& remove_duplicates(); + void resize(size_type count) { this->Values.resize(count); } + enum class FilterMode { INCLUDE, @@ -880,46 +944,61 @@ public: // ============== // these methods can be used to store CMake list expansion directly in a // std::vector. - static void assign(cm::string_view value, - std::vector<std::string>& container, + static void assign(std::vector<std::string>& container, + cm::string_view value, + EmptyElements emptyElements = EmptyElements::No) + { + container.clear(); + cmList::append(container, value, emptyElements); + } + static void assign(std::vector<std::string>& container, + std::string const& value, EmptyElements emptyElements = EmptyElements::No) { container.clear(); - cmList::append(value, container, emptyElements); + cmList::append(container, value, emptyElements); } - static void assign(cmValue value, std::vector<std::string>& container, + static void assign(std::vector<std::string>& container, cmValue value, EmptyElements emptyElements = EmptyElements::No) { if (value) { - cmList::assign(*value, container, emptyElements); + cmList::assign(container, *value, emptyElements); } else { container.clear(); } } template <typename InputIterator> - static void assign(InputIterator first, InputIterator last, - std::vector<std::string>& container, + static void assign(std::vector<std::string>& container, InputIterator first, + InputIterator last, EmptyElements emptyElements = EmptyElements::No) { container.clear(); - cmList::append(first, last, container, emptyElements); + cmList::append(container, first, last, emptyElements); } static std::vector<std::string>::iterator insert( - std::vector<std::string>::const_iterator pos, cm::string_view value, std::vector<std::string>& container, + std::vector<std::string>::const_iterator pos, cm::string_view value, EmptyElements emptyElements = EmptyElements::No) { - return cmList::Insert(pos, std::string(value), container, + return cmList::Insert(container, pos, std::string(value), ExpandElements::Yes, emptyElements); } static std::vector<std::string>::iterator insert( - std::vector<std::string>::const_iterator pos, cmValue value, std::vector<std::string>& container, + std::vector<std::string>::const_iterator pos, std::string const& value, + EmptyElements emptyElements = EmptyElements::No) + { + return cmList::Insert(container, pos, value, ExpandElements::Yes, + emptyElements); + } + static std::vector<std::string>::iterator insert( + std::vector<std::string>& container, + std::vector<std::string>::const_iterator pos, cmValue value, EmptyElements emptyElements = EmptyElements::No) { if (value) { - return cmList::insert(pos, *value, container, emptyElements); + return cmList::insert(container, pos, *value, emptyElements); } auto delta = std::distance(container.cbegin(), pos); @@ -927,63 +1006,73 @@ public: } template <typename InputIterator> static std::vector<std::string>::iterator insert( + std::vector<std::string>& container, std::vector<std::string>::const_iterator pos, InputIterator first, - InputIterator last, std::vector<std::string>& container, - EmptyElements emptyElements = EmptyElements::No) + InputIterator last, EmptyElements emptyElements = EmptyElements::No) { - return cmList::Insert(pos, first, last, container, ExpandElements::Yes, + return cmList::Insert(container, pos, first, last, ExpandElements::Yes, emptyElements); } static std::vector<std::string>::iterator append( - cm::string_view value, std::vector<std::string>& container, + std::vector<std::string>& container, cm::string_view value, EmptyElements emptyElements = EmptyElements::No) { - return cmList::insert(container.cend(), value, container, emptyElements); + return cmList::insert(container, container.cend(), value, emptyElements); } static std::vector<std::string>::iterator append( - cmValue value, std::vector<std::string>& container, + std::vector<std::string>& container, std::string const& value, + EmptyElements emptyElements = EmptyElements::No) + { + return cmList::insert(container, container.cend(), value, emptyElements); + } + static std::vector<std::string>::iterator append( + std::vector<std::string>& container, cmValue value, EmptyElements emptyElements = EmptyElements::No) { if (value) { - return cmList::append(*value, container, emptyElements); + return cmList::append(container, *value, emptyElements); } return container.end(); } template <typename InputIterator> static std::vector<std::string>::iterator append( - InputIterator first, InputIterator last, - std::vector<std::string>& container, - EmptyElements emptyElements = EmptyElements::No) + std::vector<std::string>& container, InputIterator first, + InputIterator last, EmptyElements emptyElements = EmptyElements::No) { - return cmList::insert(container.cend(), first, last, container, + return cmList::insert(container, container.cend(), first, last, emptyElements); } static std::vector<std::string>::iterator prepend( - cm::string_view value, std::vector<std::string>& container, + std::vector<std::string>& container, cm::string_view value, + EmptyElements emptyElements = EmptyElements::No) + { + return cmList::insert(container, container.cbegin(), value, emptyElements); + } + static std::vector<std::string>::iterator prepend( + std::vector<std::string>& container, std::string const& value, EmptyElements emptyElements = EmptyElements::No) { - return cmList::insert(container.cbegin(), value, container, emptyElements); + return cmList::insert(container, container.cbegin(), value, emptyElements); } static std::vector<std::string>::iterator prepend( - cmValue value, std::vector<std::string>& container, + std::vector<std::string>& container, cmValue value, EmptyElements emptyElements = EmptyElements::No) { if (value) { - return cmList::prepend(*value, container, emptyElements); + return cmList::prepend(container, *value, emptyElements); } return container.begin(); } template <typename InputIterator> static std::vector<std::string>::iterator prepend( - InputIterator first, InputIterator last, - std::vector<std::string>& container, - EmptyElements emptyElements = EmptyElements::No) + std::vector<std::string>& container, InputIterator first, + InputIterator last, EmptyElements emptyElements = EmptyElements::No) { - return cmList::insert(container.cbegin(), first, last, container, + return cmList::insert(container, container.cbegin(), first, last, emptyElements); } @@ -991,40 +1080,40 @@ public: // but without any intermediate expansion. So the operation is simply a // string concatenation with special handling for the CMake list item // separator - static std::string& append(cm::string_view value, std::string& list); + static std::string& append(std::string& list, cm::string_view value); template <typename InputIterator> - static std::string& append(InputIterator first, InputIterator last, - std::string& list) + static std::string& append(std::string& list, InputIterator first, + InputIterator last) { if (first == last) { return list; } - return cmList::append(cm::string_view{ std::accumulate( + return cmList::append(list, + cm::string_view{ std::accumulate( std::next(first), last, *first, [](std::string a, const std::string& b) { return std::move(a) + std::string(cmList::element_separator) + b; - }) }, - list); + }) }); } - static std::string& prepend(cm::string_view value, std::string& list); + static std::string& prepend(std::string& list, cm::string_view value); template <typename InputIterator> - static std::string& prepend(InputIterator first, InputIterator last, - std::string& list) + static std::string& prepend(std::string& list, InputIterator first, + InputIterator last) { if (first == last) { return list; } - return cmList::prepend(cm::string_view{ std::accumulate( + return cmList::prepend(list, + cm::string_view{ std::accumulate( std::next(first), last, *first, [](std::string a, const std::string& b) { return std::move(a) + std::string(cmList::element_separator) + b; - }) }, - list); + }) }); } // Non-members @@ -1047,26 +1136,26 @@ private: cmList& RemoveItems(std::vector<index_type>&& indexes); cmList& RemoveItems(std::vector<std::string>&& items); - static container_type::iterator Insert(container_type::const_iterator pos, + static container_type::iterator Insert(container_type& container, + container_type::const_iterator pos, std::string&& value, - container_type& container, ExpandElements expandElements, EmptyElements emptyElements); - static container_type::iterator Insert(container_type::const_iterator pos, + static container_type::iterator Insert(container_type& container, + container_type::const_iterator pos, const std::string& value, - container_type& container, ExpandElements expandElements, EmptyElements emptyElements) { auto tmp = value; - return cmList::Insert(pos, std::move(tmp), container, expandElements, + return cmList::Insert(container, pos, std::move(tmp), expandElements, emptyElements); } template <typename InputIterator> - static container_type::iterator Insert(container_type::const_iterator pos, + static container_type::iterator Insert(container_type& container, + container_type::const_iterator pos, InputIterator first, InputIterator last, - container_type& container, ExpandElements expandElements, EmptyElements emptyElements) { @@ -1080,7 +1169,7 @@ private: if (expandElements == ExpandElements::Yes) { for (; first != last; ++first) { auto size = container.size(); - insertPos = cmList::Insert(insertPos, *first, container, + insertPos = cmList::Insert(container, insertPos, *first, expandElements, emptyElements); insertPos += container.size() - size; } @@ -1177,6 +1266,13 @@ inline std::vector<std::string>& operator+=(std::vector<std::string>& l, return l; } +namespace std { +inline void swap(cmList& lhs, cmList& rhs) noexcept +{ + lhs.swap(rhs); +} +} // namespace std + namespace cm { inline void erase(cmList& list, const std::string& value) { @@ -1188,11 +1284,69 @@ inline void erase_if(cmList& list, Predicate pred) { list.erase(std::remove_if(list.begin(), list.end(), pred), list.end()); } + +// +// Provide a special implementation of cm::append because, in this case, +// expansion must not be applied to the inserted elements +// +#if defined(__SUNPRO_CC) && defined(__sparc) +// Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile +// templates with constraints. +// So, on this platform, use only simple templates. +template <typename InputIt, + cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = 0> +void append(cmList& v, InputIt first, InputIt last) +{ + v.append(first, last, cmList::ExpandElements::No); } -namespace srd { -inline void swap(cmList& lhs, cmList& rhs) noexcept +template <typename Range, + cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0> +void append(cmList& v, Range const& r) { - lhs.swap(rhs); + v.append(r.begin(), r.end(), cmList::ExpandElements::No); +} + +#else + +template < + typename InputIt, + cm::enable_if_t< + cm::is_input_iterator<InputIt>::value && + std::is_convertible<typename std::iterator_traits<InputIt>::value_type, + cmList::value_type>::value, + int> = 0> +void append(cmList& v, InputIt first, InputIt last) +{ + v.append(first, last, cmList::ExpandElements::No); +} + +template <typename Range, + cm::enable_if_t<cm::is_input_range<Range>::value && + std::is_convertible<typename Range::value_type, + cmList::value_type>::value, + int> = 0> +void append(cmList& v, Range const& r) +{ + v.append(r.begin(), r.end(), cmList::ExpandElements::No); } +#endif + +} // namespace cm + +/** + * Helper functions for legacy support. Use preferably cmList class directly + * or the static methods of the class. + */ +inline void cmExpandList( + cm::string_view arg, std::vector<std::string>& argsOut, + cmList::EmptyElements emptyElements = cmList::EmptyElements::No) +{ + cmList::append(argsOut, arg, emptyElements); +} +inline void cmExpandList( + cmValue arg, std::vector<std::string>& argsOut, + cmList::EmptyElements emptyElements = cmList::EmptyElements::No) +{ + cmList::append(argsOut, arg, emptyElements); } diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 40be0ceeb5..acffa2ec81 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -205,7 +205,7 @@ bool HandleAppendCommand(std::vector<std::string> const& args, GetListString(listString, listName, makefile); makefile.AddDefinition( - listName, cmList::append(args.begin() + 2, args.end(), listString)); + listName, cmList::append(listString, args.begin() + 2, args.end())); return true; } @@ -226,7 +226,7 @@ bool HandlePrependCommand(std::vector<std::string> const& args, GetListString(listString, listName, makefile); makefile.AddDefinition( - listName, cmList::prepend(args.begin() + 2, args.end(), listString)); + listName, cmList::prepend(listString, args.begin() + 2, args.end())); return true; } diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 6270c825f2..97f5de9697 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -11,10 +11,10 @@ # include <cmsys/Encoding.hxx> #endif +#include "cmList.h" #include "cmListFileLexer.h" #include "cmMessageType.h" #include "cmMessenger.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" struct cmListFileParser @@ -496,10 +496,11 @@ std::ostream& operator<<(std::ostream& os, BT<std::string> const& s) } std::vector<BT<std::string>> cmExpandListWithBacktrace( - std::string const& list, cmListFileBacktrace const& bt, bool emptyArgs) + std::string const& list, cmListFileBacktrace const& bt, + cmList::EmptyElements emptyArgs) { std::vector<BT<std::string>> result; - std::vector<std::string> tmp = cmExpandedList(list, emptyArgs); + cmList tmp{ list, emptyArgs }; result.reserve(tmp.size()); for (std::string& i : tmp) { result.emplace_back(std::move(i), bt); diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 05539892c9..e4e6eb37ed 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -13,6 +13,7 @@ #include <cm/optional> #include "cmConstStack.h" +#include "cmList.h" #include "cmSystemTools.h" /** \class cmListFileCache @@ -232,7 +233,7 @@ public: std::vector<BT<std::string>> cmExpandListWithBacktrace( std::string const& list, cmListFileBacktrace const& bt = cmListFileBacktrace(), - bool emptyArgs = false); + cmList::EmptyElements emptyArgs = cmList::EmptyElements::No); struct cmListFile { diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index eca7a9eb6e..aa953f469d 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -8,7 +8,6 @@ #include "cmGeneratorTarget.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" @@ -17,9 +16,8 @@ class cmGlobalGenerator; cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, - cmMakefile* mf, WorkDir wd) + cmMakefile* mf) : cmLocalGenerator(gg, mf) - , WorkingDirectory(wd) { this->ConfigNames = this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); @@ -29,21 +27,9 @@ cmLocalCommonGenerator::~cmLocalCommonGenerator() = default; std::string const& cmLocalCommonGenerator::GetWorkingDirectory() const { - if (this->WorkingDirectory == WorkDir::TopBin) { - return this->GetState()->GetBinaryDirectory(); - } return this->StateSnapshot.GetDirectory().GetCurrentBinary(); } -std::string cmLocalCommonGenerator::MaybeRelativeToWorkDir( - std::string const& path) const -{ - if (this->WorkingDirectory == WorkDir::TopBin) { - return this->MaybeRelativeToTopBinDir(path); - } - return this->MaybeRelativeToCurBinDir(path); -} - std::string cmLocalCommonGenerator::GetTargetFortranFlags( cmGeneratorTarget const* target, std::string const& config) { diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index 0505c138d1..52f7a9e5e6 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -20,15 +20,8 @@ class cmSourceFile; */ class cmLocalCommonGenerator : public cmLocalGenerator { -protected: - enum class WorkDir - { - TopBin, - CurBin, - }; - public: - cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf, WorkDir wd); + cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf); ~cmLocalCommonGenerator() override; std::vector<std::string> const& GetConfigNames() const @@ -36,9 +29,7 @@ public: return this->ConfigNames; } - std::string const& GetWorkingDirectory() const; - - std::string MaybeRelativeToWorkDir(std::string const& path) const; + virtual std::string const& GetWorkingDirectory() const; std::string GetTargetFortranFlags(cmGeneratorTarget const* target, std::string const& config) override; @@ -48,8 +39,6 @@ public: cmGeneratorTarget const* gt = nullptr) override; protected: - WorkDir WorkingDirectory; - std::vector<std::string> ConfigNames; friend class cmCommonTargetGenerator; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 01e4241360..4089fd440b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -38,6 +38,7 @@ #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" #include "cmLinkLineDeviceComputer.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" @@ -146,12 +147,10 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) { std::string const& appleArchs = this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES"); - std::vector<std::string> archs; - std::vector<std::string> sysroots; - cmExpandList(appleArchs, archs); - cmExpandList(*appleArchSysroots, sysroots, true); + cmList archs(appleArchs); + cmList sysroots{ appleArchSysroots, cmList::EmptyElements::Yes }; if (archs.size() == sysroots.size()) { - for (size_t i = 0; i < archs.size(); ++i) { + for (cmList::size_type i = 0; i < archs.size(); ++i) { this->AppleArchSysroots[archs[i]] = sysroots[i]; } } else { @@ -208,12 +207,12 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) } } -cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander() - const +std::unique_ptr<cmRulePlaceholderExpander> +cmLocalGenerator::CreateRulePlaceholderExpander() const { - return new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings, - this->CompilerSysroot, - this->LinkerSysroot); + return cm::make_unique<cmRulePlaceholderExpander>( + this->Compilers, this->VariableMappings, this->CompilerSysroot, + this->LinkerSysroot); } cmLocalGenerator::~cmLocalGenerator() = default; @@ -347,7 +346,7 @@ void cmLocalGenerator::GenerateTestFiles() cmValue testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES"); if (testIncludeFiles) { - std::vector<std::string> includesList = cmExpandedList(*testIncludeFiles); + cmList includesList{ *testIncludeFiles }; for (std::string const& i : includesList) { fout << "include(\"" << i << "\")\n"; } @@ -1064,9 +1063,9 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, std::string isJMCEnabled = cmGeneratorExpression::Evaluate(*jmcExprGen, this, config); if (cmIsOn(isJMCEnabled)) { - std::vector<std::string> optVec = cmExpandedList(*jmc); + cmList optList{ *jmc }; std::string jmcFlags; - this->AppendCompileOptions(jmcFlags, optVec); + this->AppendCompileOptions(jmcFlags, optList); if (!jmcFlags.empty()) { flags.emplace_back(std::move(jmcFlags)); } @@ -1168,11 +1167,11 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // Standard include directories to be added unconditionally at the end. // These are intended to simulate additional implicit include directories. - std::vector<std::string> userStandardDirs; + cmList userStandardDirs; { std::string const value = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_STANDARD_INCLUDE_DIRECTORIES")); - cmExpandList(value, userStandardDirs); + userStandardDirs.assign(value); for (std::string& usd : userStandardDirs) { cmSystemTools::ConvertToUnixSlashes(usd); } @@ -1195,13 +1194,12 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // directories for modules ('.mod' files). if (lang != "Fortran") { size_t const impDirVecOldSize = impDirVec.size(); - if (this->Makefile->GetDefExpandList( - cmStrCat("CMAKE_", lang, "_IMPLICIT_INCLUDE_DIRECTORIES"), - impDirVec)) { - // FIXME: Use cmRange with 'advance()' when it supports non-const. - for (size_t i = impDirVecOldSize; i < impDirVec.size(); ++i) { - cmSystemTools::ConvertToUnixSlashes(impDirVec[i]); - } + cmList::append(impDirVec, + this->Makefile->GetDefinition(cmStrCat( + "CMAKE_", lang, "_IMPLICIT_INCLUDE_DIRECTORIES"))); + // FIXME: Use cmRange with 'advance()' when it supports non-const. + for (size_t i = impDirVecOldSize; i < impDirVec.size(); ++i) { + cmSystemTools::ConvertToUnixSlashes(impDirVec[i]); } } @@ -1588,6 +1586,8 @@ void cmLocalGenerator::GetTargetFlags( this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config, linkLanguage); this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage); + this->AppendDependencyInfoLinkerFlags(extraLinkFlags, target, config, + linkLanguage); this->AppendModuleDefinitionFlag(extraLinkFlags, target, linkLineComputer, config); @@ -1954,8 +1954,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, cmValue opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef); if (opt) { - std::vector<std::string> optVec = cmExpandedList(*opt); - for (std::string const& i : optVec) { + cmList optList{ *opt }; + for (std::string const& i : optList) { this->AppendFlagEscape(flags, i); } } @@ -2426,7 +2426,7 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_PIC")); } if (!picFlags.empty()) { - std::vector<std::string> options = cmExpandedList(picFlags); + cmList options{ picFlags }; for (std::string const& o : options) { this->AppendFlagEscape(flags, o); } @@ -2447,10 +2447,9 @@ void cmLocalGenerator::AddColorDiagnosticsFlags(std::string& flags, cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_COLOR_DIAGNOSTICS_OFF"); } - std::vector<std::string> options; - this->Makefile->GetDefExpandList(colorFlagName, options); + cmList options{ this->Makefile->GetDefinition(colorFlagName) }; - for (std::string const& option : options) { + for (auto const& option : options) { this->AppendFlagEscape(flags, option); } } @@ -2973,6 +2972,7 @@ void cmLocalGenerator::WriteUnitySourceInclude( unity_file << *beforeInclude << "\n"; } + unity_file << "// NOLINTNEXTLINE(bugprone-suspicious-include)\n"; unity_file << "#include \"" << sf_full_path << "\"\n"; if (afterInclude) { @@ -3163,7 +3163,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, return; } - std::vector<std::string> flagsList = cmExpandedList(*rawFlagsList); + cmList flagsList{ *rawFlagsList }; for (std::string const& o : flagsList) { this->AppendFlagEscape(flags, o); } @@ -3198,12 +3198,47 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags( return; } - std::vector<std::string> flagsList = cmExpandedList(pieFlags); + cmList flagsList{ pieFlags }; for (const auto& flag : flagsList) { this->AppendFlagEscape(flags, flag); } } +void cmLocalGenerator::AppendDependencyInfoLinkerFlags( + std::string& flags, cmGeneratorTarget* target, const std::string& config, + const std::string& linkLanguage) +{ + if (!this->GetGlobalGenerator()->SupportsLinkerDependencyFile() || + !target->HasLinkDependencyFile(config)) { + return; + } + + auto depFlag = *this->Makefile->GetDefinition( + cmStrCat("CMAKE_", linkLanguage, "_LINKER_DEPFILE_FLAGS")); + if (depFlag.empty()) { + return; + } + + auto depFile = this->ConvertToOutputFormat( + this->MaybeRelativeToWorkDir(this->GetLinkDependencyFile(target, config)), + cmOutputConverter::SHELL); + auto rulePlaceholderExpander = this->CreateRulePlaceholderExpander(); + cmRulePlaceholderExpander::RuleVariables linkDepsVariables; + linkDepsVariables.DependencyFile = depFile.c_str(); + rulePlaceholderExpander->ExpandRuleVariables(this, depFlag, + linkDepsVariables); + auto depFlags = cmExpandListWithBacktrace(depFlag); + target->ResolveLinkerWrapper(depFlags, linkLanguage); + + this->AppendFlags(flags, depFlags); +} + +std::string cmLocalGenerator::GetLinkDependencyFile( + cmGeneratorTarget* /*target*/, const std::string& /*config*/) const +{ + return "link.d"; +} + void cmLocalGenerator::AppendModuleDefinitionFlag( std::string& flags, cmGeneratorTarget const* target, cmLinkLineComputer* linkLineComputer, std::string const& config) @@ -3264,7 +3299,7 @@ void cmLocalGenerator::AppendCompileOptions(std::string& options, } // Expand the list of options. - std::vector<std::string> options_vec = cmExpandedList(options_list); + cmList options_vec{ options_list }; this->AppendCompileOptions(options, options_vec, regex); } @@ -3322,7 +3357,7 @@ void cmLocalGenerator::AppendIncludeDirectories( } // Expand the list of includes. - std::vector<std::string> includes_vec = cmExpandedList(includes_list); + cmList includes_vec{ includes_list }; this->AppendIncludeDirectories(includes, includes_vec, sourceFile); } @@ -3454,7 +3489,7 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags, cmValue optionList = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature)); if (optionList) { - std::vector<std::string> options = cmExpandedList(*optionList); + cmList options{ *optionList }; for (std::string const& o : options) { this->AppendFlagEscape(flags, o); } @@ -4385,12 +4420,11 @@ void AddUtilityCommand(cmLocalGenerator& lg, cmCommandOrigin origin, std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target) { - const std::string& targetProperty = - target->GetSafeProperty("ISPC_INSTRUCTION_SETS"); - std::vector<std::string> ispcTargets; + const cmValue targetProperty = target->GetProperty("ISPC_INSTRUCTION_SETS"); + cmList ispcTargets; - if (!cmIsOff(targetProperty)) { - cmExpandList(targetProperty, ispcTargets); + if (!targetProperty.IsOff()) { + ispcTargets.assign(targetProperty); for (auto& ispcTarget : ispcTargets) { // transform targets into the suffixes auto pos = ispcTarget.find('-'); @@ -4402,7 +4436,7 @@ std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target) ispcTarget = target_suffix; } } - return ispcTargets; + return std::move(ispcTargets.data()); } std::vector<std::string> ComputeISPCExtraObjects( @@ -4500,11 +4534,11 @@ cmLocalGenerator::MakeCustomCommandGenerators(cmCustomCommand const& cc, std::vector<std::string> cmLocalGenerator::ExpandCustomCommandOutputPaths( cmCompiledGeneratorExpression const& cge, std::string const& config) { - std::vector<std::string> paths = cmExpandedList(cge.Evaluate(this, config)); + cmList paths{ cge.Evaluate(this, config) }; for (std::string& p : paths) { p = cmSystemTools::CollapseFullPath(p, this->GetCurrentBinaryDirectory()); } - return paths; + return std::move(paths.data()); } std::vector<std::string> cmLocalGenerator::ExpandCustomCommandOutputGenex( diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index bda82bce00..c811408138 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -89,7 +89,7 @@ class cmLocalGenerator : public cmOutputConverter { public: cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile); - virtual ~cmLocalGenerator(); + ~cmLocalGenerator() override; /** * Generate the makefile for this directory. @@ -137,7 +137,8 @@ public: return this->GlobalGenerator; } - virtual cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const; + virtual std::unique_ptr<cmRulePlaceholderExpander> + CreateRulePlaceholderExpander() const; std::string GetLinkLibsCMP0065(std::string const& linkLanguage, cmGeneratorTarget& tgt) const; @@ -183,6 +184,12 @@ public: cmGeneratorTarget* target, const std::string& config, const std::string& lang); + void AppendDependencyInfoLinkerFlags(std::string& flags, + cmGeneratorTarget* target, + const std::string& config, + const std::string& lang); + virtual std::string GetLinkDependencyFile(cmGeneratorTarget* target, + const std::string& config) const; void AppendModuleDefinitionFlag(std::string& flags, cmGeneratorTarget const* target, cmLinkLineComputer* linkLineComputer, diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index d0bd3758f4..4b0604c55e 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -22,6 +22,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalNinjaGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -40,19 +41,18 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmMakefile* mf) - : cmLocalCommonGenerator(gg, mf, WorkDir::TopBin) + : cmLocalCommonGenerator(gg, mf) { } // Virtual public methods. -cmRulePlaceholderExpander* +std::unique_ptr<cmRulePlaceholderExpander> cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const { - cmRulePlaceholderExpander* ret = - this->cmLocalGenerator::CreateRulePlaceholderExpander(); + auto ret = this->cmLocalGenerator::CreateRulePlaceholderExpander(); ret->SetTargetImpLib("$TARGET_IMPLIB"); - return ret; + return std::unique_ptr<cmRulePlaceholderExpander>(std::move(ret)); } cmLocalNinjaGenerator::~cmLocalNinjaGenerator() = default; @@ -187,6 +187,26 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator() return static_cast<cmGlobalNinjaGenerator*>(this->GetGlobalGenerator()); } +std::string const& cmLocalNinjaGenerator::GetWorkingDirectory() const +{ + return this->GetState()->GetBinaryDirectory(); +} + +std::string cmLocalNinjaGenerator::MaybeRelativeToWorkDir( + std::string const& path) const +{ + return this->GetGlobalNinjaGenerator()->NinjaOutputPath( + this->MaybeRelativeToTopBinDir(path)); +} + +std::string cmLocalNinjaGenerator::GetLinkDependencyFile( + cmGeneratorTarget* target, std::string const& config) const +{ + return cmStrCat(target->GetSupportDirectory(), + this->GetGlobalNinjaGenerator()->ConfigDirectory(config), + "/link.d"); +} + // Virtual protected methods. std::string cmLocalNinjaGenerator::ConvertToIncludeReference( @@ -301,7 +321,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) if (jobpools) { cmGlobalNinjaGenerator::WriteComment( os, "Pools defined by global property JOB_POOLS"); - std::vector<std::string> pools = cmExpandedList(*jobpools); + cmList pools{ *jobpools }; for (std::string const& pool : pools) { const std::string::size_type eq = pool.find('='); unsigned int jobs; @@ -892,8 +912,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( } vars.Output = output.c_str(); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = this->CreateRulePlaceholderExpander(); std::string launcher = *property_value; rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars); @@ -908,14 +927,11 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) { if (cmValue prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { - std::vector<std::string> cleanFiles; - { - cmExpandList(cmGeneratorExpression::Evaluate(*prop_value, this, config), - cleanFiles); - } + cmList cleanFiles{ cmGeneratorExpression::Evaluate(*prop_value, this, + config) }; std::string const& binaryDir = this->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); - for (std::string const& cleanFile : cleanFiles) { + for (auto const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 4d393d9c3a..74b8b3b3f8 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -6,6 +6,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -41,7 +42,8 @@ public: void Generate() override; - cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const override; + std::unique_ptr<cmRulePlaceholderExpander> CreateRulePlaceholderExpander() + const override; std::string GetTargetDirectory( cmGeneratorTarget const* target) const override; @@ -52,6 +54,10 @@ public: const cmake* GetCMakeInstance() const; cmake* GetCMakeInstance(); + std::string const& GetWorkingDirectory() const override; + + std::string MaybeRelativeToWorkDir(std::string const& path) const override; + /// @returns the relative path between the HomeOutputDirectory and this /// local generators StartOutputDirectory. std::string GetHomeRelativeOutputPath() const @@ -90,6 +96,9 @@ public: bool HasUniqueByproducts(std::vector<std::string> const& byproducts, cmListFileBacktrace const& bt); + std::string GetLinkDependencyFile(cmGeneratorTarget* target, + std::string const& config) const override; + protected: std::string ConvertToIncludeReference( std::string const& path, cmOutputConverter::OutputFormat format) override; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 56a41b1a98..cfe4eb629d 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -29,6 +29,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -110,7 +111,7 @@ private: cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3( cmGlobalGenerator* gg, cmMakefile* mf) - : cmLocalCommonGenerator(gg, mf, WorkDir::CurBin) + : cmLocalCommonGenerator(gg, mf) { this->MakefileVariableSize = 0; this->ColorMakefile = false; @@ -238,6 +239,12 @@ void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets( } } +std::string cmLocalUnixMakefileGenerator3::GetLinkDependencyFile( + cmGeneratorTarget* target, std::string const& /*config*/) const +{ + return cmStrCat(target->GetSupportDirectory(), "/link.d"); +} + void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() { // generate the includes @@ -962,8 +969,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( *content << dir; } - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = this->CreateRulePlaceholderExpander(); // Add each command line to the set of commands. std::vector<std::string> commands1; @@ -1129,14 +1135,13 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand( void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( std::vector<std::string>& commands) { - std::vector<std::string> cleanFiles; + cmList cleanFiles; // Look for additional files registered for cleaning in this directory. if (cmValue prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { - cmExpandList(cmGeneratorExpression::Evaluate( - *prop_value, this, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), - cleanFiles); + cleanFiles.assign(cmGeneratorExpression::Evaluate( + *prop_value, this, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))); } if (cleanFiles.empty()) { return; @@ -1434,7 +1439,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES"); if (!depends.empty()) { // dependencies are managed by compiler - auto depFiles = cmExpandedList(depends, true); + cmList depFiles{ depends, cmList::EmptyElements::Yes }; std::string const internalDepFile = targetDir + "/compiler_depend.internal"; std::string const depFile = targetDir + "/compiler_depend.make"; @@ -1556,8 +1561,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( this->WriteDisclaimer(internalRuleFileStream); // for each language we need to scan, scan it - std::vector<std::string> langs = - cmExpandedList(mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES")); + cmList langs{ mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES") }; for (std::string const& lang : langs) { // construct the checker // Create the scanner for this language @@ -1602,7 +1606,7 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) } // Convert the string to a list and preserve empty entries. - std::vector<std::string> pairs = cmExpandedList(*pairs_string, true); + cmList pairs{ *pairs_string, cmList::EmptyElements::Yes }; for (auto i = pairs.begin(); i != pairs.end() && (i + 1) != pairs.end();) { const std::string& depender = *i++; const std::string& dependee = *i++; @@ -1822,7 +1826,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, if (!infoDef) { return; } - std::vector<std::string> files = cmExpandedList(*infoDef); + cmList files{ *infoDef }; // Each depend information file corresponds to a target. Clear the // dependencies for that target. @@ -1863,7 +1867,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, cmSystemTools::Touch(DepTimestamp.GenericString(), true); // clear the dependencies files generated by the compiler - std::vector<std::string> dependencies = cmExpandedList(depsFiles, true); + cmList dependencies{ depsFiles, cmList::EmptyElements::Yes }; cmDependsCompiler depsManager; depsManager.SetVerbose(verbose); depsManager.ClearDependencies(dependencies); @@ -1973,14 +1977,14 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Store include transform rule properties. Write the directory // rules first because they may be overridden by later target rules. - std::vector<std::string> transformRules; + cmList transformRules; if (cmValue xform = this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { - cmExpandList(*xform, transformRules); + transformRules.assign(*xform); } if (cmValue xform = target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { - cmExpandList(*xform, transformRules); + transformRules.append(*xform); } if (!transformRules.empty()) { cmakefileStream << "\nset(CMAKE_INCLUDE_TRANSFORMS\n"; @@ -2009,6 +2013,18 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( << this->MaybeRelativeToTopBinDir(src) << "\"\n"; } } + } else if (compilerLang.first == "LINK"_s) { + auto depFormat = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", target->GetLinkerLanguage(this->GetConfigName()), + "_LINKER_DEPFILE_FORMAT")); + for (auto const& compilerPair : compilerPairs) { + for (auto const& src : compilerPair.second) { + cmakefileStream << R"( "" ")" + << this->MaybeRelativeToTopBinDir(compilerPair.first) + << "\" \"" << depFormat << "\" \"" + << this->MaybeRelativeToTopBinDir(src) << "\"\n"; + } + } } else { auto depFormat = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT")); diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 78aa7f9c2f..7d5a9224b4 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -191,6 +191,9 @@ public: // Eclipse generator. void GetIndividualFileTargets(std::vector<std::string>& targets); + std::string GetLinkDependencyFile(cmGeneratorTarget* target, + std::string const& config) const override; + protected: void WriteLocalMakefile(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 239748db67..a7ea0dff2c 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -29,6 +29,7 @@ #include "cmGlobalGenerator.h" #include "cmGlobalVisualStudio7Generator.h" #include "cmGlobalVisualStudioGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmOutputConverter.h" @@ -1576,12 +1577,12 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( // Check for extra object-file dependencies. if (cmValue deps = sf.GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> depends = cmExpandedList(*deps); - const char* sep = ""; - for (const std::string& d : depends) { - fc.AdditionalDeps += sep; - fc.AdditionalDeps += lg->ConvertToXMLOutputPath(d); - sep = ";"; + cmList depends{ *deps }; + if (!depends.empty()) { + for (std::string& d : depends) { + d = lg->ConvertToXMLOutputPath(d); + } + fc.AdditionalDeps += depends.to_string(); needfc = true; } } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 3a69b2eeed..01afc44f28 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -43,6 +43,7 @@ #include "cmGlobalGenerator.h" #include "cmInstallGenerator.h" // IWYU pragma: keep #include "cmInstallSubdirectoryGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMessageType.h" @@ -1448,15 +1449,13 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) if (remove) { if (cmValue cdefs = this->GetProperty("COMPILE_DEFINITIONS")) { // Expand the list. - std::vector<std::string> defs = cmExpandedList(*cdefs); + cmList defs{ *cdefs }; // Recompose the list without the definition. - auto defEnd = std::remove(defs.begin(), defs.end(), define); - auto defBegin = defs.begin(); - std::string ndefs = cmJoin(cmMakeRange(defBegin, defEnd), ";"); + defs.remove_items({ define }); // Store the new list. - this->SetProperty("COMPILE_DEFINITIONS", ndefs); + this->SetProperty("COMPILE_DEFINITIONS", defs.to_string()); } } else { // Append the definition to the directory property. @@ -1958,21 +1957,15 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, value = existingValue->c_str(); } if (type == cmStateEnums::PATH || type == cmStateEnums::FILEPATH) { - std::vector<std::string>::size_type cc; - std::vector<std::string> files; nvalue = value ? value : ""; - cmExpandList(nvalue, files); - nvalue.clear(); - for (cc = 0; cc < files.size(); cc++) { - if (!cmIsOff(files[cc])) { - files[cc] = cmSystemTools::CollapseFullPath(files[cc]); + cmList files(nvalue); + for (auto& file : files) { + if (!cmIsOff(file)) { + file = cmSystemTools::CollapseFullPath(file); } - if (cc > 0) { - nvalue += ";"; - } - nvalue += files[cc]; } + nvalue = files.to_string(); this->GetCMakeInstance()->AddCacheEntry(name, nvalue, doc, type); nvalue = *this->GetState()->GetInitializedCacheValue(name); @@ -2064,7 +2057,7 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) } if (cmValue linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { - std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp); + cmList linkLibs{ *linkLibsProp }; for (auto j = linkLibs.begin(); j != linkLibs.end(); ++j) { std::string libraryName = *j; @@ -2378,7 +2371,7 @@ void cmMakefile::ExpandVariablesCMP0019() } if (cmValue linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { - std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp); + cmList linkLibs{ *linkLibsProp }; for (auto l = linkLibs.begin(); l != linkLibs.end(); ++l) { std::string libName = *l; @@ -2614,18 +2607,6 @@ const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const return this->GetDefinition(name); } -bool cmMakefile::GetDefExpandList(const std::string& name, - std::vector<std::string>& out, - bool emptyArgs) const -{ - cmValue def = this->GetDefinition(name); - if (!def) { - return false; - } - cmExpandList(*def, out, emptyArgs); - return true; -} - std::vector<std::string> cmMakefile::GetDefinitions() const { std::vector<std::string> res = this->StateSnapshot.ClosureKeys(); @@ -3266,9 +3247,9 @@ std::string cmMakefile::GetDefaultConfiguration() const std::vector<std::string> cmMakefile::GetGeneratorConfigs( GeneratorConfigQuery mode) const { - std::vector<std::string> configs; + cmList configs; if (this->GetGlobalGenerator()->IsMultiConfig()) { - this->GetDefExpandList("CMAKE_CONFIGURATION_TYPES", configs); + configs.assign(this->GetDefinition("CMAKE_CONFIGURATION_TYPES")); } else if (mode != cmMakefile::OnlyMultiConfig) { const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE"); if (!buildType.empty()) { @@ -3278,7 +3259,7 @@ std::vector<std::string> cmMakefile::GetGeneratorConfigs( if (mode == cmMakefile::IncludeEmptyConfig && configs.empty()) { configs.emplace_back(); } - return configs; + return std::move(configs.data()); } bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff, @@ -3406,7 +3387,7 @@ bool cmMakefile::ExpandArguments( if (i.Delim == cmListFileArgument::Quoted) { outArgs.emplace_back(value, true); } else { - std::vector<std::string> stringArgs = cmExpandedList(value); + cmList stringArgs{ value }; for (std::string const& stringArg : stringArgs) { outArgs.emplace_back(stringArg, false); } @@ -3812,7 +3793,7 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, // Always search in CMAKE_MODULE_PATH: cmValue cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH"); if (cmakeModulePath) { - std::vector<std::string> modulePath = cmExpandedList(*cmakeModulePath); + cmList modulePath{ *cmakeModulePath }; // Look through the possible module directories. for (std::string itempl : modulePath) { @@ -4155,11 +4136,11 @@ void cmMakefile::GetTests(const std::string& config, void cmMakefile::AddCMakeDependFilesFromUser() { - std::vector<std::string> deps; + cmList deps; if (cmValue deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) { - cmExpandList(*deps_str, deps); + deps.assign(*deps_str); } - for (std::string const& dep : deps) { + for (auto const& dep : deps) { if (cmSystemTools::FileIsFullPath(dep)) { this->AddCMakeDependFile(dep); } else { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index a43ff41f9c..d1f5be53a0 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -518,8 +518,6 @@ public: const std::string& GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; bool IsNormalDefinitionSet(const std::string&) const; - bool GetDefExpandList(const std::string& name, std::vector<std::string>& out, - bool emptyArgs = false) const; /** * Get the list of all variables in the current space. If argument * cacheonly is specified and is greater than 0, then only cache diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 196007328e..4a2b9e8996 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -16,6 +16,7 @@ #include "cmGlobalUnixMakefileGenerator3.h" #include "cmLinkLineComputer.h" #include "cmLinkLineDeviceComputer.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -69,6 +70,8 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() this->WriteExecutableRule(true); } + this->WriteTargetLinkDependRules(); + // Write clean target this->WriteTargetCleanRules(); @@ -151,11 +154,10 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( bool useLinkScript = this->GlobalGenerator->GetUseLinkScript(); // Construct the main link rule. - std::vector<std::string> real_link_commands; const std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE"; const std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector<std::string> commands1; - cmExpandList(linkRule, real_link_commands); + cmList real_link_commands(linkRule); bool useResponseFileForObjects = this->CheckUseResponseFileForObjects(linkLanguage); @@ -230,12 +232,12 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( launcher = cmStrCat(val, ' '); } - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->LocalGenerator->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->LocalGenerator->CreateRulePlaceholderExpander(); // Expand placeholders in the commands. rulePlaceholderExpander->SetTargetImpLib(targetOutput); - for (std::string& real_link_command : real_link_commands) { + for (auto& real_link_command : real_link_commands) { real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); @@ -466,18 +468,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) bool useLinkScript = this->GlobalGenerator->GetUseLinkScript(); // Construct the main link rule. - std::vector<std::string> real_link_commands; std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( linkLanguage, this->GetConfigName()); std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector<std::string> commands1; - cmExpandList(linkRule, real_link_commands); + cmList real_link_commands(linkRule); + if (this->GeneratorTarget->IsExecutableWithExports()) { // If a separate rule for creating an import library is specified // add it now. std::string implibRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_IMPORT_LIBRARY"); - this->Makefile->GetDefExpandList(implibRuleVar, real_link_commands); + real_link_commands.append(this->Makefile->GetDefinition(implibRuleVar)); } bool useResponseFileForObjects = @@ -596,12 +598,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) launcher = cmStrCat(val, ' '); } - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->LocalGenerator->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->LocalGenerator->CreateRulePlaceholderExpander(); // Expand placeholders in the commands. rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport); - for (std::string& real_link_command : real_link_commands) { + for (auto& real_link_command : real_link_commands) { real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 3e4a08ee27..b07a74b568 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -16,6 +16,7 @@ #include "cmGlobalUnixMakefileGenerator3.h" #include "cmLinkLineComputer.h" #include "cmLinkLineDeviceComputer.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -61,6 +62,9 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() // write in rules for object files and custom commands this->WriteTargetBuildRules(); + // Write in the rules for the link dependency file + this->WriteTargetLinkDependRules(); + // write the link rules // Write the rule for this target type. switch (this->GeneratorTarget->GetType()) { @@ -304,7 +308,7 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( vars.Language = linkLanguage.c_str(); // Expand the rule variables. - std::vector<std::string> real_link_commands; + cmList real_link_commands; { // Set path conversion for link script shells. this->LocalGenerator->SetLinkScriptShell(useLinkScript); @@ -369,16 +373,16 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( launcher = cmStrCat(val, ' '); } - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->LocalGenerator->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->LocalGenerator->CreateRulePlaceholderExpander(); // Construct the main link rule and expand placeholders. rulePlaceholderExpander->SetTargetImpLib(targetOutput); std::string linkRule = this->GetLinkRule(linkRuleVar); - cmExpandList(linkRule, real_link_commands); + real_link_commands.append(linkRule); // Expand placeholders. - for (std::string& real_link_command : real_link_commands) { + for (auto& real_link_command : real_link_commands) { real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); @@ -640,9 +644,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // For static libraries there might be archiving rules. bool haveStaticLibraryRule = false; - std::vector<std::string> archiveCreateCommands; - std::vector<std::string> archiveAppendCommands; - std::vector<std::string> archiveFinishCommands; + cmList archiveCreateCommands; + cmList archiveAppendCommands; + cmList archiveFinishCommands; std::string::size_type archiveCommandLimit = std::string::npos; if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { haveStaticLibraryRule = this->Makefile->IsDefinitionSet(linkRuleVar); @@ -652,21 +656,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( arCreateVar, linkLanguage, this->GetConfigName()); - this->Makefile->GetDefExpandList(arCreateVar, archiveCreateCommands); + archiveCreateCommands.assign(this->Makefile->GetDefinition(arCreateVar)); + std::string arAppendVar = cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND"); arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( arAppendVar, linkLanguage, this->GetConfigName()); - this->Makefile->GetDefExpandList(arAppendVar, archiveAppendCommands); + archiveAppendCommands.assign(this->Makefile->GetDefinition(arAppendVar)); + std::string arFinishVar = cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH"); arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( arFinishVar, linkLanguage, this->GetConfigName()); - this->Makefile->GetDefExpandList(arFinishVar, archiveFinishCommands); + archiveFinishCommands.assign(this->Makefile->GetDefinition(arFinishVar)); } // Decide whether to use archiving rules. @@ -690,11 +696,11 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // Expand the rule variables. - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->LocalGenerator->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->LocalGenerator->CreateRulePlaceholderExpander(); bool useWatcomQuote = this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE"); - std::vector<std::string> real_link_commands; + cmList real_link_commands; { // Set path conversion for link script shells. this->LocalGenerator->SetLinkScriptShell(useLinkScript); @@ -879,7 +885,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } else { // Get the set of commands. std::string linkRule = this->GetLinkRule(linkRuleVar); - cmExpandList(linkRule, real_link_commands); + real_link_commands.append(linkRule); if (this->UseLWYU) { cmValue lwyuCheck = this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); @@ -895,7 +901,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // Expand placeholders. - for (std::string& real_link_command : real_link_commands) { + for (auto& real_link_command : real_link_commands) { real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); @@ -965,7 +971,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->GeneratorTarget->HasImportLibrary(this->GetConfigName())) { auto genStubsRule = this->Makefile->GetDefinition("CMAKE_CREATE_TEXT_STUBS"); - auto genStubs_commands = cmExpandedList(genStubsRule); + cmList genStubs_commands{ genStubsRule }; std::string TBDFullPath = cmStrCat(outpathImp, this->TargetNames.ImportOutput); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 3112acd578..02cdf57275 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -29,6 +29,7 @@ #include "cmGlobalCommonGenerator.h" #include "cmGlobalUnixMakefileGenerator3.h" #include "cmLinkLineComputer.h" // IWYU pragma: keep +#include "cmList.h" #include "cmLocalCommonGenerator.h" #include "cmLocalGenerator.h" #include "cmLocalUnixMakefileGenerator3.h" @@ -149,6 +150,8 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( this->LocalGenerator->AppendPositionIndependentLinkerFlags( flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); + this->LocalGenerator->AppendDependencyInfoLinkerFlags( + flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); } void cmMakefileTargetGenerator::CreateRuleFile() @@ -207,27 +210,24 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // -- Write the custom commands for this target // Evaluates generator expressions and expands prop_value - auto evaluatedFiles = - [this](const std::string& prop_value) -> std::vector<std::string> { - std::vector<std::string> files; - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, this->LocalGenerator, this->GetConfigName(), - this->GeneratorTarget), - files); + auto evaluatedFiles = [this](const std::string& prop_value) -> cmList { + cmList files{ cmGeneratorExpression::Evaluate( + prop_value, this->LocalGenerator, this->GetConfigName(), + this->GeneratorTarget) }; return files; }; // Look for additional files registered for cleaning in this directory. if (cmValue prop_value = this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) { - std::vector<std::string> const files = evaluatedFiles(*prop_value); + auto const files = evaluatedFiles(*prop_value); this->CleanFiles.insert(files.begin(), files.end()); } // Look for additional files registered for cleaning in this target. if (cmValue prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { - std::vector<std::string> const files = evaluatedFiles(*prop_value); + auto const files = evaluatedFiles(*prop_value); // For relative path support std::string const& binaryDir = this->LocalGenerator->GetCurrentBinaryDirectory(); @@ -416,8 +416,10 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->GlobalGenerator->SupportsCompilerDependencies() && (!this->Makefile->IsDefinitionSet(depsUseCompiler) || this->Makefile->IsOn(depsUseCompiler)); + bool linkerGenerateDeps = + this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName()); - if (compilerGenerateDeps || ccGenerateDeps) { + if (compilerGenerateDeps || linkerGenerateDeps || ccGenerateDeps) { std::string compilerDependFile = cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make"); *this->BuildFileStream << "# Include any dependencies generated by the " @@ -965,8 +967,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( bool const lang_has_assembly = lang_has_preprocessor; bool const lang_can_export_cmds = lang_has_preprocessor; - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->LocalGenerator->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->LocalGenerator->CreateRulePlaceholderExpander(); // Construct the compile rules. { @@ -1002,10 +1004,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.CudaCompileMode = cudaCompileMode.c_str(); } - std::vector<std::string> compileCommands; + cmList compileCommands; const std::string& compileRule = this->Makefile->GetRequiredDefinition( "CMAKE_" + lang + "_COMPILE_OBJECT"); - cmExpandList(compileRule, compileCommands); + compileCommands.assign(compileRule); if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") && lang_can_export_cmds && compileCommands.size() == 1) { @@ -1200,7 +1202,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // If compiler launcher was specified and not consumed above, it // goes to the beginning of the command line. if (!compileCommands.empty() && !compilerLauncher.empty()) { - std::vector<std::string> args = cmExpandedList(compilerLauncher, true); + cmList args{ compilerLauncher, cmList::EmptyElements::Yes }; if (!args.empty()) { args[0] = this->LocalGenerator->ConvertToOutputFormat( args[0], cmOutputConverter::SHELL); @@ -1208,7 +1210,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( i = this->LocalGenerator->EscapeForShell(i); } } - compileCommands.front().insert(0, cmJoin(args, " ") + " "); + compileCommands.front().insert(0, args.join(" ") + " "); } std::string launcher; @@ -1240,9 +1242,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( const auto& extraCommands = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS")); if (!extraCommands.empty()) { - auto commandList = cmExpandedList(extraCommands); - compileCommands.insert(compileCommands.end(), commandList.cbegin(), - commandList.cend()); + compileCommands.append(extraCommands); } const auto& depFormat = this->Makefile->GetRequiredDefinition( @@ -1283,14 +1283,15 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } // Check for extra outputs created by the compilation. - std::vector<std::string> outputs(1, relativeObj); + cmList outputs; + outputs.emplace_back(relativeObj); if (cmValue extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) { std::string evaluated_outputs = cmGeneratorExpression::Evaluate( *extra_outputs_str, this->LocalGenerator, config); if (!evaluated_outputs.empty()) { // Register these as extra files to clean. - cmExpandList(evaluated_outputs, outputs); + outputs.append(evaluated_outputs); } } if (!ispcHeaderRelative.empty()) { @@ -1341,8 +1342,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE"); if (cmValue preprocessRule = this->Makefile->GetDefinition(preprocessRuleVar)) { - std::vector<std::string> preprocessCommands = - cmExpandedList(*preprocessRule); + cmList preprocessCommands{ *preprocessRule }; std::string shellObjI = this->LocalGenerator->ConvertToOutputFormat( objI, cmOutputConverter::SHELL); @@ -1386,8 +1386,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE"); if (cmValue assemblyRule = this->Makefile->GetDefinition(assemblyRuleVar)) { - std::vector<std::string> assemblyCommands = - cmExpandedList(*assemblyRule); + cmList assemblyCommands{ *assemblyRule }; std::string shellObjS = this->LocalGenerator->ConvertToOutputFormat( objS, cmOutputConverter::SHELL); @@ -1504,6 +1503,21 @@ bool cmMakefileTargetGenerator::WriteMakeRule( return symbolic; } +void cmMakefileTargetGenerator::WriteTargetLinkDependRules() +{ + if (!this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName())) { + return; + } + + auto depFile = this->LocalGenerator->GetLinkDependencyFile( + this->GeneratorTarget, this->GetConfigName()); + this->CleanFiles.insert(depFile); + this->LocalGenerator->AddImplicitDepends( + this->GeneratorTarget, "LINK", + this->GeneratorTarget->GetFullPath(this->GetConfigName()), depFile, + cmDependencyScannerKind::Compiler); +} + void cmMakefileTargetGenerator::WriteTargetDependRules() { // must write the targets depend info file @@ -1674,7 +1688,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( } cmLocalUnixMakefileGenerator3* localGen{ this->LocalGenerator }; - std::vector<std::string> architectures = cmExpandedList(architecturesStr); + cmList architectures{ architecturesStr }; std::string const& relPath = localGen->GetHomeRelativeOutputPath(); // Ensure there are no duplicates. @@ -1775,8 +1789,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( vars.Flags = flags.c_str(); std::string compileCmd = this->GetLinkRule("CMAKE_CUDA_DEVICE_LINK_COMPILE"); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - localGen->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = localGen->CreateRulePlaceholderExpander(); rulePlaceholderExpander->ExpandRuleVariables(localGen, compileCmd, vars); commands.emplace_back(compileCmd); @@ -2057,8 +2070,14 @@ void cmMakefileTargetGenerator::AppendTargetDepends( return; } - // Loop over all library dependencies. const std::string& cfg = this->GetConfigName(); + + if (this->GeneratorTarget->HasLinkDependencyFile(cfg)) { + depends.push_back( + cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")); + } + + // Loop over all library dependencies. if (cmComputeLinkInformation* cli = this->GeneratorTarget->GetLinkInformation(cfg)) { cm::append(depends, cli->GetDepends()); diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 98c3a0e8db..ef7a60fa62 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -77,6 +77,8 @@ protected: // write the clean rules for this target void WriteTargetCleanRules(); + // write the linker depend rules for this target + void WriteTargetLinkDependRules(); // write the depend rules for this target void WriteTargetDependRules(); diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 52373f3160..baf40f8258 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -10,6 +10,7 @@ #include "cmConfigureLog.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmMessenger.h" @@ -31,13 +32,13 @@ enum class CheckingType std::string IndentText(std::string text, cmMakefile& mf) { auto indent = - cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), ""); + cmList{ mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT") }.join(""); const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() || mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW"); if (showContext) { - auto context = cmJoin( - cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), "."); + auto context = + cmList{ mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT") }.join("."); if (!context.empty()) { indent.insert(0u, cmStrCat("["_s, context, "] "_s)); } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 4d68460521..063ca6ba6a 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -23,6 +23,7 @@ #include "cmGlobalNinjaGenerator.h" #include "cmLinkLineComputer.h" #include "cmLinkLineDeviceComputer.h" +#include "cmList.h" #include "cmLocalCommonGenerator.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" @@ -213,6 +214,22 @@ std::string cmNinjaNormalTargetGenerator::TextStubsGeneratorRule( '_', config); } +bool cmNinjaNormalTargetGenerator::CheckUseResponseFileForLibraries( + const std::string& l) const +{ + // Check for an explicit setting one way or the other. + std::string const responseVar = + "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES"; + + // If the option is defined, read it's value + if (cmValue val = this->Makefile->GetDefinition(responseVar)) { + return val.IsOn(); + } + + // Default to true + return true; +} + struct cmNinjaRemoveNoOpCommands { bool operator()(std::string const& cmd) @@ -251,9 +268,16 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule( } else { rule.RspContent = "$in_newline"; } - rule.RspContent += " $LINK_LIBRARIES"; + + // add the link command in the file if necessary + if (this->CheckUseResponseFileForLibraries("CUDA")) { + rule.RspContent += " $LINK_LIBRARIES"; + vars.LinkLibraries = ""; + } else { + vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES"; + } + vars.Objects = responseFlag.c_str(); - vars.LinkLibraries = ""; } vars.ObjectDir = "$OBJECT_DIR"; @@ -278,8 +302,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule( launcher = cmStrCat(val, ' '); } - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->GetLocalGenerator()->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); // Rule for linking library/executable. std::vector<std::string> linkCmds = this->ComputeDeviceLinkCmd(); @@ -338,8 +362,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( std::string compileCmd = this->GetMakefile()->GetRequiredDefinition( "CMAKE_CUDA_DEVICE_LINK_COMPILE"); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->GetLocalGenerator()->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), compileCmd, vars); @@ -393,6 +417,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); + if (this->GeneratorTarget->HasLinkDependencyFile(config)) { + auto DepFileFormat = this->GetMakefile()->GetDefinition( + cmStrCat(cmakeVarLang, "_LINKER_DEPFILE_FORMAT")); + rule.DepType = DepFileFormat; + rule.DepFile = "$DEP_FILE"; + } + // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); @@ -416,13 +447,20 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, } else { rule.RspContent = "$in_newline"; } - rule.RspContent += " $LINK_PATH $LINK_LIBRARIES"; + + // If libraries in rsp is enable + if (this->CheckUseResponseFileForLibraries(lang)) { + rule.RspContent += " $LINK_PATH $LINK_LIBRARIES"; + vars.LinkLibraries = ""; + } else { + vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES"; + } + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftSources = responseFlag.c_str(); } else { vars.Objects = responseFlag.c_str(); } - vars.LinkLibraries = ""; } vars.ObjectDir = "$OBJECT_DIR"; @@ -473,8 +511,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, launcher = cmStrCat(val, ' '); } - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->GetLocalGenerator()->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); // Rule for linking library/executable. std::vector<std::string> linkCmds = this->ComputeLinkCmd(config); @@ -546,8 +584,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, std::string cmd = this->GetMakefile()->GetDefinition("CMAKE_CREATE_TEXT_STUBS"); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->GetLocalGenerator()->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); cmRulePlaceholderExpander::RuleVariables vars; vars.Target = "$in"; rulePlaceholderExpander->SetTargetImpLib("$out"); @@ -579,7 +617,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() { - std::vector<std::string> linkCmds; + cmList linkCmds; // this target requires separable cuda compilation // now build the correct command depending on if the target is @@ -588,23 +626,23 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { - this->GetMakefile()->GetDefExpandList("CMAKE_CUDA_DEVICE_LINK_LIBRARY", - linkCmds); + linkCmds.assign( + this->GetMakefile()->GetDefinition("CMAKE_CUDA_DEVICE_LINK_LIBRARY")); } break; case cmStateEnums::EXECUTABLE: { - this->GetMakefile()->GetDefExpandList( - "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE", linkCmds); + linkCmds.assign(this->GetMakefile()->GetDefinition( + "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE")); } break; default: break; } - return linkCmds; + return std::move(linkCmds.data()); } std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( const std::string& config) { - std::vector<std::string> linkCmds; + cmList linkCmds; cmMakefile* mf = this->GetMakefile(); { // If we have a rule variable prefer it. In the case of static libraries @@ -623,7 +661,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( linkCmdStr += *rule; } } - cmExpandList(linkCmdStr, linkCmds); + linkCmds.assign(linkCmdStr); if (this->UseLWYU) { cmValue lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); if (lwyuCheck) { @@ -642,7 +680,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( linkCmds.push_back(std::move(cmakeCommand)); } } - return linkCmds; + return std::move(linkCmds.data()); } } switch (this->GetGeneratorTarget()->GetType()) { @@ -663,7 +701,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); - cmExpandList(linkCmd, linkCmds); + linkCmds.append(linkCmd); } { std::string linkCmdVar = cmStrCat( @@ -673,7 +711,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); - cmExpandList(linkCmd, linkCmds); + linkCmds.append(linkCmd); } #ifdef __APPLE__ // On macOS ranlib truncates the fractional part of the static archive @@ -697,7 +735,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( default: assert(false && "Unexpected target type"); } - return linkCmds; + return std::move(linkCmds.data()); } void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( @@ -754,7 +792,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( } this->WriteDeviceLinkRules(config); - this->WriteDeviceLinkStatements(config, cmExpandedList(architecturesStr), + this->WriteDeviceLinkStatements(config, cmList{ architecturesStr }, targetOutputReal); } else { this->WriteNvidiaDeviceLinkStatement(config, fileConfig, targetOutputDir, @@ -1103,6 +1141,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmNinjaBuild linkBuild(this->LanguageLinkerRule(config)); cmNinjaVars& vars = linkBuild.Variables; + if (this->GeneratorTarget->HasLinkDependencyFile(config)) { + vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( + this->ConvertToNinjaPath( + this->GetLocalGenerator()->GetLinkDependencyFile(this->GeneratorTarget, + config)), + cmOutputConverter::SHELL); + } + // Compute the comment. linkBuild.Comment = cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal); diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index 85f42a4487..187ea4627a 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -26,7 +26,7 @@ private: const std::string& config) const; std::string LanguageLinkerCudaFatbinaryRule(const std::string& config) const; std::string TextStubsGeneratorRule(const std::string& config) const; - + bool CheckUseResponseFileForLibraries(const std::string& config) const; const char* GetVisibleTypeName() const; void WriteLanguagesRules(const std::string& config); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 5dbc283fac..4ed491d33c 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -9,6 +9,7 @@ #include <iterator> #include <map> #include <ostream> +#include <type_traits> #include <unordered_map> #include <unordered_set> #include <utility> @@ -21,8 +22,6 @@ #include <cm3p/json/value.h> #include <cm3p/json/writer.h> -#include "cmsys/RegularExpression.hxx" - #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmDyndepCollation.h" @@ -32,6 +31,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalCommonGenerator.h" #include "cmGlobalNinjaGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" @@ -665,8 +665,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, std::string const modmapFormat = this->Makefile->GetSafeDefinition(modmapFormatVar); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->GetLocalGenerator()->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)), @@ -689,7 +689,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, // Rule to scan dependencies of sources that need preprocessing. { - std::vector<std::string> scanCommands; + cmList scanCommands; std::string scanRuleName; std::string ppFileName; if (compilationPreprocesses) { @@ -697,8 +697,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, ppFileName = "$PREPROCESSED_OUTPUT_FILE"; std::string const& scanCommand = mf->GetRequiredDefinition( cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_SOURCE")); - cmExpandList(scanCommand, scanCommands); - for (std::string& i : scanCommands) { + scanCommands.assign(scanCommand); + for (auto& i : scanCommands) { i = cmStrCat(launcher, i); } } else { @@ -706,8 +706,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, ppFileName = "$out"; std::string const& ppCommmand = mf->GetRequiredDefinition( cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE")); - cmExpandList(ppCommmand, scanCommands); - for (std::string& i : scanCommands) { + scanCommands.assign(ppCommmand); + for (auto& i : scanCommands) { i = cmStrCat(launcher, i); } scanCommands.emplace_back(GetScanCommand(cmakeCmd, tdi, lang, "$out", @@ -886,10 +886,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, } // Rule for compiling object file. - std::vector<std::string> compileCmds; const std::string cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT"); const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); - cmExpandList(compileCmd, compileCmds); + cmList compileCmds(compileCmd); // See if we need to use a compiler launcher like ccache or distcc std::string compilerLauncher; @@ -1038,7 +1037,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, // If compiler launcher was specified and not consumed above, it // goes to the beginning of the command line. if (!compileCmds.empty() && !compilerLauncher.empty()) { - std::vector<std::string> args = cmExpandedList(compilerLauncher, true); + cmList args{ compilerLauncher, cmList::EmptyElements::Yes }; if (!args.empty()) { args[0] = this->LocalGenerator->ConvertToOutputFormat( args[0], cmOutputConverter::SHELL); @@ -1046,7 +1045,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, i = this->LocalGenerator->EscapeForShell(i); } } - compileCmds.front().insert(0, cmStrCat(cmJoin(args, " "), ' ')); + compileCmds.front().insert(0, cmStrCat(args.join(" "), ' ')); } if (!compileCmds.empty()) { @@ -1056,12 +1055,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, const auto& extraCommands = this->GetMakefile()->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS")); if (!extraCommands.empty()) { - auto commandList = cmExpandedList(extraCommands); - compileCmds.insert(compileCmds.end(), commandList.cbegin(), - commandList.cend()); + compileCmds.append(extraCommands); } - for (std::string& i : compileCmds) { + for (auto& i : compileCmds) { i = cmStrCat(launcher, i); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i, vars); @@ -1261,7 +1258,6 @@ namespace { cmNinjaBuild GetScanBuildStatement(const std::string& ruleName, const std::string& ppFileName, bool compilePP, bool compilePPWithDefines, - cmValue ppExcludeFlagsRegex, cmNinjaBuild& objBuild, cmNinjaVars& vars, const std::string& objectFileName, cmLocalGenerator* lg) @@ -1290,20 +1286,6 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName, // Scanning and compilation generally use the same flags. scanBuild.Variables["FLAGS"] = vars["FLAGS"]; - // Exclude flags not valid during preprocessing. - if (compilePP && !ppExcludeFlagsRegex.IsEmpty()) { - std::string in = std::move(scanBuild.Variables["FLAGS"]); - std::string out; - cmsys::RegularExpression regex(*ppExcludeFlagsRegex); - std::string::size_type pos = 0; - while (regex.find(in.c_str() + pos)) { - out = cmStrCat(out, in.substr(pos, regex.start()), ' '); - pos += regex.end(); - } - out = cmStrCat(out, in.substr(pos)); - scanBuild.Variables["FLAGS"] = std::move(out); - } - if (compilePP && !compilePPWithDefines) { // Move preprocessor definitions to the scan/preprocessor build statement. std::swap(scanBuild.Variables["DEFINES"], vars["DEFINES"]); @@ -1468,7 +1450,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } if (cmValue objectDeps = source->GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> objDepList = cmExpandedList(*objectDeps); + cmList objDepList{ *objectDeps }; std::copy(objDepList.begin(), objDepList.end(), std::back_inserter(depList)); } @@ -1528,22 +1510,18 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string scanRuleName; std::string ppFileName; - cmValue ppExcludeFlagsRegex; if (compilePP) { scanRuleName = this->LanguagePreprocessAndScanRule(language, config); ppFileName = this->ConvertToNinjaPath( this->GetPreprocessedFilePath(source, config)); - ppExcludeFlagsRegex = this->Makefile->GetDefinition(cmStrCat( - "CMAKE_", language, "_PREPROCESS_SOURCE_EXCLUDE_FLAGS_REGEX")); } else { scanRuleName = this->LanguageScanRule(language, config); ppFileName = cmStrCat(objectFileName, ".ddi.i"); } cmNinjaBuild ppBuild = GetScanBuildStatement( - scanRuleName, ppFileName, compilePP, compilePPWithDefines, - ppExcludeFlagsRegex, objBuild, vars, objectFileName, - this->LocalGenerator); + scanRuleName, ppFileName, compilePP, compilePPWithDefines, objBuild, + vars, objectFileName, this->LocalGenerator); if (compilePP) { // In case compilation requires flags that are incompatible with @@ -1688,7 +1666,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( if (!evaluatedObjectOutputs.empty()) { cmNinjaBuild build("phony"); build.Comment = "Additional output files."; - build.Outputs = cmExpandedList(evaluatedObjectOutputs); + build.Outputs = cmList{ evaluatedObjectOutputs }.data(); std::transform(build.Outputs.begin(), build.Outputs.end(), build.Outputs.begin(), this->MapToNinjaPath()); build.ExplicitDeps = objBuild.Outputs; @@ -1882,16 +1860,15 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( compileObjectVars.CudaCompileMode = cudaCompileMode.c_str(); } - std::vector<std::string> compileCmds; const std::string cmdVar = cmStrCat("CMAKE_", language, "_COMPILE_OBJECT"); const std::string& compileCmd = this->Makefile->GetRequiredDefinition(cmdVar); - cmExpandList(compileCmd, compileCmds); + cmList compileCmds(compileCmd); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( - this->GetLocalGenerator()->CreateRulePlaceholderExpander()); + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); - for (std::string& i : compileCmds) { + for (auto& i : compileCmds) { // no launcher for CMAKE_EXPORT_COMPILE_COMMANDS rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i, compileObjectVars); @@ -1909,13 +1886,11 @@ void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) if (cmValue prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmLocalNinjaGenerator* lg = this->LocalGenerator; - std::vector<std::string> cleanFiles; - cmExpandList(cmGeneratorExpression::Evaluate(*prop_value, lg, config, - this->GeneratorTarget), - cleanFiles); + cmList cleanFiles(cmGeneratorExpression::Evaluate(*prop_value, lg, config, + this->GeneratorTarget)); std::string const& binaryDir = lg->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator(); - for (std::string const& cleanFile : cleanFiles) { + for (auto const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 6c54e01e3d..53cb21e59d 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -6,16 +6,15 @@ #include <cassert> #include <cctype> #include <set> -#include <vector> #ifdef _WIN32 # include <unordered_map> # include <utility> #endif +#include "cmList.h" #include "cmState.h" #include "cmStateDirectory.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -176,7 +175,12 @@ std::string cmOutputConverter::ConvertToOutputForExisting( } std::string tmp{}; - cmSystemTools::GetShortPath(remote, tmp); + cmsys::Status status = cmSystemTools::GetShortPath(remote, tmp); + if (!status) { + // Fallback for cases when Windows refuses to resolve the short path, + // like for C:\Program Files\WindowsApps\... + tmp = remote; + } shortPathCache[remote] = tmp; return tmp; }(); @@ -319,7 +323,7 @@ cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( { FortranFormat format = FortranFormatNone; if (!value.empty()) { - for (std::string const& fi : cmExpandedList(value)) { + for (std::string const& fi : cmList(value)) { if (fi == "FIXED") { format = FortranFormatFixed; } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 2717bdd1c2..625d89768c 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -16,6 +16,7 @@ class cmOutputConverter { public: cmOutputConverter(cmStateSnapshot const& snapshot); + virtual ~cmOutputConverter() = default; /** * Convert the given remote path to a relative path with respect to @@ -27,6 +28,15 @@ public: std::string MaybeRelativeToTopBinDir(std::string const& path) const; std::string MaybeRelativeToCurBinDir(std::string const& path) const; + /** + * The effective working directory can be different for each generator. + * By default, equivalent to the current binary directory. + */ + virtual std::string MaybeRelativeToWorkDir(std::string const& path) const + { + return this->MaybeRelativeToCurBinDir(path); + } + std::string const& GetRelativePathTopSource() const; std::string const& GetRelativePathTopBinary() const; void SetRelativePathTop(std::string const& topSource, diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index ad276d2f70..f147ed22de 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -14,6 +14,7 @@ #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" @@ -126,9 +127,9 @@ public: std::string incDirs = cmGeneratorExpression::Preprocess( *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); - std::vector<std::string> includes = cmExpandedList(incDirs); + cmList includes{ incDirs }; - for (std::string& path : includes) { + for (auto& path : includes) { this->Makefile->ExpandVariablesInString(path); if (uniqueIncludes.insert(path).second) { orderedAndUniqueIncludes.push_back(path); diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 7e195664e2..b0462f056a 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -12,6 +12,7 @@ #include "cmArgumentParser.h" #include "cmArgumentParserTypes.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" @@ -169,17 +170,15 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args, }; // the second argument is a (cmake) list of options without argument - std::vector<std::string> list = cmExpandedList(*argIter++); + cmList list{ *argIter++ }; parser.Bind(list, options, duplicateKey); // the third argument is a (cmake) list of single argument options - list.clear(); - cmExpandList(*argIter++, list); + list.assign(*argIter++); parser.Bind(list, singleValArgs, duplicateKey); // the fourth argument is a (cmake) list of multi argument options - list.clear(); - cmExpandList(*argIter++, list); + list.assign(*argIter++); parser.Bind(list, multiValArgs, duplicateKey); list.clear(); @@ -187,7 +186,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args, // Flatten ;-lists in the arguments into a single list as was done // by the original function(CMAKE_PARSE_ARGUMENTS). for (; argIter != argEnd; ++argIter) { - cmExpandList(*argIter, list); + list.append(*argIter); } } else { // in the PARSE_ARGV move read the arguments from ARGC and ARGV# diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index fe883826aa..a0030d3dc1 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -450,7 +450,16 @@ class cmMakefile; 27, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0149, \ "Visual Studio generators select latest Windows SDK by default.", 3, \ - 27, 0, cmPolicies::WARN) + 27, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0150, \ + "ExternalProject_Add and FetchContent_Declare commands " \ + "treat relative GIT_REPOSITORY paths as being relative " \ + "to the parent project's remote.", \ + 3, 27, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0151, \ + "AUTOMOC include directory is a system include directory by " \ + "default.", \ + 3, 27, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 782c154653..d897f0e5be 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -35,6 +35,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -507,7 +508,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() std::string const& deps = this->GenTarget->GetSafeProperty("AUTOGEN_TARGET_DEPENDS"); if (!deps.empty()) { - for (std::string const& depName : cmExpandedList(deps)) { + for (auto const& depName : cmList{ deps }) { // Allow target and file dependencies auto* depTarget = this->Makefile->FindTargetToUse(depName); if (depTarget) { @@ -545,8 +546,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames), this->Moc.MacroNames.end()); { - auto filterList = cmExpandedList( - this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); + cmList filterList = { this->GenTarget->GetSafeProperty( + "AUTOMOC_DEPEND_FILTERS") }; if ((filterList.size() % 2) != 0) { cmSystemTools::Error( cmStrCat("AutoMoc: AUTOMOC_DEPEND_FILTERS predefs size ", @@ -558,7 +559,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() "Q_PLUGIN_METADATA", "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" "[^\\)]*FILE[ \t]*\"([^\"]+)\""); - for (std::size_t ii = 0; ii != filterList.size(); ii += 2) { + for (cmList::size_type ii = 0; ii != filterList.size(); ii += 2) { this->Moc.DependFilters.emplace_back(filterList[ii], filterList[ii + 1]); } @@ -573,7 +574,31 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Add autogen include directory to the origin target INCLUDE_DIRECTORIES if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) { - this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, true); + auto addBefore = false; + auto const& value = + this->GenTarget->GetProperty("AUTOGEN_USE_SYSTEM_INCLUDE"); + if (value.IsSet()) { + if (cmIsOn(value)) { + this->GenTarget->AddSystemIncludeDirectory(this->Dir.IncludeGenExp, + "CXX"); + } else { + addBefore = true; + } + } else { + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0151)) { + case cmPolicies::WARN: + case cmPolicies::OLD: + addBefore = true; + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + this->GenTarget->AddSystemIncludeDirectory(this->Dir.IncludeGenExp, + "CXX"); + break; + } + } + this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, addBefore); } // Scan files @@ -613,8 +638,9 @@ bool cmQtAutoGenInitializer::InitMoc() if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && (this->QtVersion >= IntegerVersion(5, 8))) { // Command - this->Makefile->GetDefExpandList("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND", - this->Moc.PredefsCmd); + cmList::assign( + this->Moc.PredefsCmd, + this->Makefile->GetDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); // Header if (!this->Moc.PredefsCmd.empty()) { this->ConfigFileNames(this->Moc.PredefsFile, @@ -701,7 +727,7 @@ bool cmQtAutoGenInitializer::InitUic() this->GenTarget->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); if (!usp.empty()) { this->Uic.SearchPaths = - SearchPathSanitizer(this->Makefile)(cmExpandedList(usp)); + SearchPathSanitizer(this->Makefile)(cmList{ usp }); } } // Uic target options @@ -961,8 +987,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (uicOpts.empty()) { this->Uic.UiFilesNoOptions.emplace_back(fullPath); } else { - this->Uic.UiFilesWithOptions.emplace_back(fullPath, - cmExpandedList(uicOpts)); + this->Uic.UiFilesWithOptions.emplace_back( + fullPath, std::move(cmList{ uicOpts }.data())); } auto uiHeaderRelativePath = cmSystemTools::RelativePath( @@ -1063,8 +1089,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!this->Rcc.Qrcs.empty()) { const bool modernQt = (this->QtVersion.Major >= 5); // Target rcc options - std::vector<std::string> optionsTarget = - cmExpandedList(this->GenTarget->GetSafeProperty(kw.AUTORCC_OPTIONS)); + cmList optionsTarget{ this->GenTarget->GetSafeProperty( + kw.AUTORCC_OPTIONS) }; // Check if file name is unique for (Qrc& qrc : this->Rcc.Qrcs) { diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx index 8af13ae2b4..65a2268bc8 100644 --- a/Source/cmRemoveCommand.cxx +++ b/Source/cmRemoveCommand.cxx @@ -3,8 +3,8 @@ #include "cmRemoveCommand.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" -#include "cmStringAlgorithms.h" #include "cmValue.h" // cmRemoveCommand @@ -25,12 +25,11 @@ bool cmRemoveCommand(std::vector<std::string> const& args, } // expand the variable - std::vector<std::string> const varArgsExpanded = cmExpandedList(*cacheValue); + cmList const varArgsExpanded{ *cacheValue }; // expand the args // check for REMOVE(VAR v1 v2 ... vn) - std::vector<std::string> const argsExpanded = - cmExpandedLists(args.begin() + 1, args.end()); + cmList const argsExpanded{ args.begin() + 1, args.end() }; // now create the new value std::string value; diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx index 4dfdfae4f9..2fbf2fa04c 100644 --- a/Source/cmRuntimeDependencyArchive.cxx +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -3,13 +3,21 @@ #include "cmRuntimeDependencyArchive.h" +#include <algorithm> +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +#include <cm/memory> + #include "cmBinUtilsLinuxELFLinker.h" #include "cmBinUtilsMacOSMachOLinker.h" #include "cmBinUtilsWindowsPELinker.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #if defined(_WIN32) @@ -22,14 +30,6 @@ # include "cmVSSetupHelper.h" #endif -#include <algorithm> -#include <sstream> -#include <string> -#include <utility> -#include <vector> - -#include <cm/memory> - #if defined(_WIN32) static void AddVisualStudioPath(std::vector<std::string>& paths, const std::string& prefix, diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index d5f6f0dc21..2b992ef285 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -9,6 +9,7 @@ #include <cm/optional> #include "cmFindCommon.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -71,7 +72,7 @@ void cmSearchPath::AddCMakePath(const std::string& variable) // Get a path from a CMake variable. if (cmValue value = this->FC->Makefile->GetDefinition(variable)) { - std::vector<std::string> expanded = cmExpandedList(*value); + cmList expanded{ *value }; for (std::string const& p : expanded) { this->AddPathInternal( @@ -95,7 +96,7 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable) // Get a path from a CMake variable. if (cmValue value = this->FC->Makefile->GetDefinition(variable)) { - std::vector<std::string> expanded = cmExpandedList(*value); + cmList expanded{ *value }; this->AddPrefixPaths( expanded, this->FC->Makefile->GetCurrentSourceDirectory().c_str()); diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index d2eac0cd7b..f6e8bc6f34 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -18,6 +18,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -349,7 +350,7 @@ struct StandardLevelComputer for (size_t i = 0; i < this->Levels.size(); ++i) { if (cmValue prop = makefile->GetDefinition( cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(*prop); + cmList props{ *prop }; if (cm::contains(props, feature)) { maxLevel = { static_cast<int>(i), this->Levels[i] }; } @@ -468,7 +469,7 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( return false; } - std::vector<std::string> availableFeatures = cmExpandedList(features); + cmList availableFeatures{ features }; if (!cm::contains(availableFeatures, feature)) { std::ostringstream e; e << "The compiler feature \"" << feature << "\" is not known to " << lang diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx index 66bf383941..e352d8dd22 100644 --- a/Source/cmStringAlgorithms.cxx +++ b/Source/cmStringAlgorithms.cxx @@ -80,77 +80,6 @@ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep) return tokens; } -void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut, - bool emptyArgs) -{ - // If argument is empty, it is an empty list. - if (!emptyArgs && arg.empty()) { - return; - } - - // if there are no ; in the name then just copy the current string - if (arg.find(';') == cm::string_view::npos) { - argsOut.emplace_back(arg); - return; - } - - std::string newArg; - // Break the string at non-escaped semicolons not nested in []. - int squareNesting = 0; - cm::string_view::iterator last = arg.begin(); - cm::string_view::iterator const cend = arg.end(); - for (cm::string_view::iterator c = last; c != cend; ++c) { - switch (*c) { - case '\\': { - // We only want to allow escaping of semicolons. Other - // escapes should not be processed here. - cm::string_view::iterator cnext = c + 1; - if ((cnext != cend) && *cnext == ';') { - newArg.append(last, c); - // Skip over the escape character - last = cnext; - c = cnext; - } - } break; - case '[': { - ++squareNesting; - } break; - case ']': { - --squareNesting; - } break; - case ';': { - // Break the string here if we are not nested inside square - // brackets. - if (squareNesting == 0) { - newArg.append(last, c); - // Skip over the semicolon - last = c + 1; - if (!newArg.empty() || emptyArgs) { - // Add the last argument if the string is not empty. - argsOut.push_back(newArg); - newArg.clear(); - } - } - } break; - default: { - // Just append this character. - } break; - } - } - newArg.append(last, cend); - if (!newArg.empty() || emptyArgs) { - // Add the last argument if the string is not empty. - argsOut.push_back(std::move(newArg)); - } -} - -std::vector<std::string> cmExpandedList(cm::string_view arg, bool emptyArgs) -{ - std::vector<std::string> argsOut; - cmExpandList(arg, argsOut, emptyArgs); - return argsOut; -} - namespace { template <std::size_t N, typename T> inline void MakeDigits(cm::string_view& view, char (&digits)[N], diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 9ea74919f6..4a9840b166 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -88,63 +88,6 @@ std::string cmJoin(cmStringRange const& rng, cm::string_view separator, /** Extract tokens that are separated by any of the characters in @a sep. */ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep); -/** - * Expand the ; separated string @a arg into multiple arguments. - * All found arguments are appended to @a argsOut. - */ -void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut, - bool emptyArgs = false); -inline void cmExpandList(cmValue arg, std::vector<std::string>& argsOut, - bool emptyArgs = false) -{ - if (arg) { - cmExpandList(*arg, argsOut, emptyArgs); - } -} - -/** - * Expand out any arguments in the string range [@a first, @a last) that have - * ; separated strings into multiple arguments. All found arguments are - * appended to @a argsOut. - */ -template <class InputIt> -void cmExpandLists(InputIt first, InputIt last, - std::vector<std::string>& argsOut) -{ - for (; first != last; ++first) { - cmExpandList(*first, argsOut); - } -} - -/** - * Same as cmExpandList but a new vector is created containing - * the expanded arguments from the string @a arg. - */ -std::vector<std::string> cmExpandedList(cm::string_view arg, - bool emptyArgs = false); -inline std::vector<std::string> cmExpandedList(cmValue arg, - bool emptyArgs = false) -{ - if (!arg) { - return {}; - } - return cmExpandedList(*arg, emptyArgs); -} - -/** - * Same as cmExpandList but a new vector is created containing the expanded - * versions of all arguments in the string range [@a first, @a last). - */ -template <class InputIt> -std::vector<std::string> cmExpandedLists(InputIt first, InputIt last) -{ - std::vector<std::string> argsOut; - for (; first != last; ++first) { - cmExpandList(*first, argsOut); - } - return argsOut; -} - /** Concatenate string pieces into a single string. */ std::string cmCatViews( std::initializer_list<std::pair<cm::string_view, std::string*>> views); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 5e558714e2..0fbe430140 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -23,6 +23,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -92,7 +93,7 @@ cmValue cmTargetPropertyComputer::GetSources<cmTarget>(cmTarget const* tgt, std::ostringstream ss; const char* sep = ""; for (auto const& entry : entries) { - std::vector<std::string> files = cmExpandedList(entry.Value); + cmList files{ entry.Value }; for (std::string const& file : files) { if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") && file.back() == '>') { @@ -396,6 +397,10 @@ TargetProperty const StaticTargetProperties[] = { { "MSVC_DEBUG_INFORMATION_FORMAT"_s, IC::CanCompileSources }, { "MSVC_RUNTIME_LIBRARY"_s, IC::CanCompileSources }, { "VS_JUST_MY_CODE_DEBUGGING"_s, IC::CanCompileSources }, + { "VS_DEBUGGER_COMMAND"_s, IC::ExecutableTarget }, + { "VS_DEBUGGER_COMMAND_ARGUMENTS"_s, IC::ExecutableTarget }, + { "VS_DEBUGGER_ENVIRONMENT"_s, IC::ExecutableTarget }, + { "VS_DEBUGGER_WORKING_DIRECTORY"_s, IC::ExecutableTarget }, // ---- OpenWatcom { "WATCOM_RUNTIME_LIBRARY"_s, IC::CanCompileSources }, // -- Language @@ -545,6 +550,7 @@ TargetProperty const StaticTargetProperties[] = { // -- Autogen { "AUTOGEN_ORIGIN_DEPENDS"_s, IC::CanCompileSources }, { "AUTOGEN_PARALLEL"_s, IC::CanCompileSources }, + { "AUTOGEN_USE_SYSTEM_INCLUDE"_s, IC::CanCompileSources }, // -- moc { "AUTOMOC_DEPEND_FILTERS"_s, IC::CanCompileSources }, // -- C++ @@ -1115,7 +1121,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (globals) { const std::string genName = mf->GetGlobalGenerator()->GetName(); if (cmHasLiteralPrefix(genName, "Visual Studio")) { - std::vector<std::string> props = cmExpandedList(*globals); + cmList props{ *globals }; const std::string vsGlobal = "VS_GLOBAL_"; for (const std::string& i : props) { // split NAME=VALUE @@ -1428,7 +1434,7 @@ public: bool operator()(BT<std::string> const& entry) { - std::vector<std::string> files = cmExpandedList(entry.Value); + cmList files{ entry.Value }; std::vector<cmSourceFileLocation> locations; locations.reserve(files.size()); std::transform(files.begin(), files.end(), std::back_inserter(locations), @@ -2967,7 +2973,7 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const auto appendEntries = [=](const std::vector<BT<std::string>>& entries) { for (auto const& entry : entries) { - auto expanded = cmExpandedList(entry.Value); + cmList expanded{ entry.Value }; std::copy(expanded.begin(), expanded.end(), inserter); } }; @@ -3029,11 +3035,11 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmValue& loc, // Track the configuration-specific property suffix. suffix = cmStrCat('_', config_upper); - std::vector<std::string> mappedConfigs; + cmList mappedConfigs; { std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper); if (cmValue mapValue = this->GetProperty(mapProp)) { - cmExpandList(*mapValue, mappedConfigs, true); + mappedConfigs.assign(*mapValue, cmList::EmptyElements::Yes); } } @@ -3115,9 +3121,9 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmValue& loc, // If we have not yet found it then the project is willing to try // any available configuration. if (!loc && !imp) { - std::vector<std::string> availableConfigs; + cmList availableConfigs; if (cmValue iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) { - cmExpandList(*iconfigs, availableConfigs); + availableConfigs.assign(*iconfigs); } for (auto aci = availableConfigs.begin(); !loc && !imp && aci != availableConfigs.end(); ++aci) { diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 53e25b5d3f..cd7ff7419d 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -13,6 +13,7 @@ #include "cmExperimental.h" #include "cmFileSet.h" #include "cmGeneratorExpression.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -320,7 +321,7 @@ bool TargetSourcesImpl::HandleOneFileSet( fileSet.first->AddDirectoryEntry( BT<std::string>(baseDirectories, this->Makefile->GetBacktrace())); if (type == "HEADERS"_s || type == "CXX_MODULE_HEADER_UNITS"_s) { - for (auto const& dir : cmExpandedList(baseDirectories)) { + for (auto const& dir : cmList{ baseDirectories }) { auto interfaceDirectoriesGenex = cmStrCat("$<BUILD_INTERFACE:", dir, ">"); if (cmFileSetVisibilityIsForSelf(visibility)) { diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 5e325dd221..c4a2bc220d 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -13,6 +13,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -147,16 +148,15 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } // Evaluate command line arguments - std::vector<std::string> argv = - this->EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config); - - // Expand arguments if COMMAND_EXPAND_LISTS is set - if (this->Test->GetCommandExpandLists()) { - argv = cmExpandedLists(argv.begin(), argv.end()); - // Expanding lists on an empty command may have left it empty - if (argv.empty()) { - argv.emplace_back(); - } + cmList argv{ + this->EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config), + // Expand arguments if COMMAND_EXPAND_LISTS is set + this->Test->GetCommandExpandLists() ? cmList::ExpandElements::Yes + : cmList::ExpandElements::No + }; + // Expanding lists on an empty command may have left it empty + if (argv.empty()) { + argv.emplace_back(); } // Check whether the command executable is a target whose name is to @@ -170,7 +170,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Prepend with the emulator when cross compiling if required. cmValue emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); if (cmNonempty(emulator)) { - std::vector<std::string> emulatorWithArgs = cmExpandedList(*emulator); + cmList emulatorWithArgs{ *emulator }; std::string emulatorExe(emulatorWithArgs[0]); cmSystemTools::ConvertToUnixSlashes(emulatorExe); os << cmOutputConverter::EscapeForCMake(emulatorExe) << " "; diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index b648d9b94f..368155c346 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -15,6 +15,7 @@ #include "cmCoreTryCompile.h" #include "cmDuration.h" #include "cmExecutionStatus.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" @@ -271,7 +272,7 @@ void TryRunCommandImpl::RunExecutable(const std::string& runArgs, const std::string& emulator = this->Makefile->GetSafeDefinition("CMAKE_CROSSCOMPILING_EMULATOR"); if (!emulator.empty()) { - std::vector<std::string> emulatorWithArgs = cmExpandedList(emulator); + cmList emulatorWithArgs{ emulator }; finalCommand += cmSystemTools::ConvertToRunCommandPath(emulatorWithArgs[0]); finalCommand += " "; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 8926f9ed15..7360bf5d75 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -9,6 +9,7 @@ #include <set> #include <sstream> +#include <cm/filesystem> #include <cm/memory> #include <cm/optional> #include <cm/string_view> @@ -31,6 +32,7 @@ #include "cmGlobalVisualStudio7Generator.h" #include "cmGlobalVisualStudioGenerator.h" #include "cmLinkLineDeviceComputer.h" +#include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalVisualStudio10Generator.h" @@ -50,6 +52,8 @@ #include "cmValue.h" #include "cmVisualStudioGeneratorOptions.h" +const std::string kBuildSystemSources = "Buildsystem Input Files"; + struct cmIDEFlagTable; static void ConvertToWindowsSlash(std::string& s); @@ -1090,10 +1094,10 @@ void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) { - std::vector<std::string> references; + cmList references; if (cmValue vsDotNetReferences = this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) { - cmExpandList(*vsDotNetReferences, references); + references.assign(*vsDotNetReferences); } cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); for (auto const& i : props.GetList()) { @@ -1110,7 +1114,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) } if (!references.empty() || !this->DotNetHintReferences.empty()) { Elem e1(e0, "ItemGroup"); - for (std::string const& ri : references) { + for (auto const& ri : references) { // if the entry from VS_DOTNET_REFERENCES is an existing file, generate // a new hint-reference and name it from the filename if (cmsys::SystemTools::FileExists(ri, true)) { @@ -1167,7 +1171,7 @@ void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0) cmValue imports = this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT"); if (imports) { - std::vector<std::string> argsSplit = cmExpandedList(*imports, false); + cmList argsSplit{ *imports }; for (auto& path : argsSplit) { if (!cmsys::SystemTools::FileIsFullPath(path)) { path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; @@ -1365,20 +1369,20 @@ void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1) void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0) { - std::vector<std::string> references; + cmList references; if (cmValue vsWinRTReferences = this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) { - cmExpandList(*vsWinRTReferences, references); + references.assign(*vsWinRTReferences); } if (this->GlobalGenerator->TargetsWindowsPhone() && this->GlobalGenerator->GetSystemVersion() == "8.0" && references.empty()) { - references.push_back("platform.winmd"); + references.push_back(std::string{ "platform.winmd" }); } if (!references.empty()) { Elem e1(e0, "ItemGroup"); - for (std::string const& ri : references) { + for (auto const& ri : references) { Elem e2(e1, "Reference"); e2.Attribute("Include", ri); e2.Element("IsWinMDFile", "true"); @@ -1949,7 +1953,13 @@ void cmVisualStudio10TargetGenerator::WriteGroups() "http://schemas.microsoft.com/developer/msbuild/2003"); for (auto const& ti : this->Tools) { - this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups); + if ((this->GeneratorTarget->GetName() == + CMAKE_CHECK_BUILD_SYSTEM_TARGET) && + (ti.first == "None")) { + this->WriteBuildSystemSources(e0, ti.first, ti.second); + } else { + this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups); + } } // Added files are images and the manifest. @@ -2020,6 +2030,18 @@ void cmVisualStudio10TargetGenerator::WriteGroups() "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;" "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms"); } + + if (this->GeneratorTarget->GetName() == + CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + for (const std::string& filter : this->BuildSystemSourcesFilters) { + std::string guidName = "SG_Filter_"; + guidName += filter; + std::string guid = this->GlobalGenerator->GetGUID(guidName); + Elem e2(e1, "Filter"); + e2.Attribute("Include", filter); + e2.Element("UniqueIdentifier", "{" + guid + "}"); + } + } } } fout << '\n'; @@ -2086,6 +2108,39 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( } } +void cmVisualStudio10TargetGenerator::WriteBuildSystemSources( + Elem& e0, std::string const& name, ToolSources const& sources) +{ + const std::string srcDir = this->Makefile->GetCurrentSourceDirectory(); + const std::string::size_type srcDirLength = srcDir.length(); + + Elem e1(e0, "ItemGroup"); + e1.SetHasElements(); + for (ToolSource const& s : sources) { + cmSourceFile const* sf = s.SourceFile; + std::string const& source = sf->GetFullPath(); + + cm::filesystem::path sourcePath(source); + bool isInSrcDir = cmHasPrefix(source, srcDir); + + std::string filter = kBuildSystemSources; + if (isInSrcDir) { + std::string parentPath = sourcePath.parent_path().string(); + if (srcDir != parentPath) { + filter += parentPath.substr(srcDirLength); + } + ConvertToWindowsSlash(filter); + this->BuildSystemSourcesFilters.insert(filter); + } + + std::string path = this->ConvertPath(source, s.RelativePath); + ConvertToWindowsSlash(path); + Elem e2(e1, name); + e2.Attribute("Include", path); + e2.Element("Filter", filter); + } +} + void cmVisualStudio10TargetGenerator::WriteHeaderSource( Elem& e1, cmSourceFile const* sf, ConfigToSettings const& toolSettings) { @@ -2113,8 +2168,8 @@ void cmVisualStudio10TargetGenerator::ParseSettingsProperty( for (const std::string& config : this->Configurations) { std::string evaluated = cge->Evaluate(this->LocalGenerator, config); - std::vector<std::string> settings = cmExpandedList(evaluated); - for (const std::string& setting : settings) { + cmList settings{ evaluated }; + for (const auto& setting : settings) { const std::string::size_type assignment = setting.find('='); if (assignment != std::string::npos) { const std::string propName = setting.substr(0, assignment); @@ -2714,16 +2769,11 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( if (lang == "ASM_NASM") { if (cmValue objectDeps = sf.GetProperty("OBJECT_DEPENDS")) { - std::string dependencies; - std::vector<std::string> depends = cmExpandedList(*objectDeps); - const char* sep = ""; - for (std::string& d : depends) { + cmList depends{ *objectDeps }; + for (auto& d : depends) { ConvertToWindowsSlash(d); - dependencies += sep; - dependencies += d; - sep = ";"; } - e2.Element("AdditionalDependencies", dependencies); + e2.Element("AdditionalDependencies", depends.join(";")); } } @@ -4767,13 +4817,13 @@ void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension( void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) { - std::vector<std::string> sdkReferences; + cmList sdkReferences; std::unique_ptr<Elem> spe1; if (cmValue vsSDKReferences = this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) { - cmExpandList(*vsSDKReferences, sdkReferences); + sdkReferences.assign(*vsSDKReferences); spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); - for (std::string const& ri : sdkReferences) { + for (auto const& ri : sdkReferences) { Elem(*spe1, "SDKReference").Attribute("Include", ri); } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 97ae69fc37..a87cb01b7e 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -193,6 +193,9 @@ private: void WriteGroupSources(Elem& e0, std::string const& name, ToolSources const& sources, std::vector<cmSourceGroup>&); + void WriteBuildSystemSources(Elem& e0, std::string const& name, + ToolSources const& sources); + void AddMissingSourceGroups(std::set<cmSourceGroup const*>& groupsUsed, const std::vector<cmSourceGroup>& allGroups); bool IsResxHeader(const std::string& headerFile); @@ -243,6 +246,7 @@ private: std::set<std::string> ASanEnabledConfigurations; std::set<std::string> FuzzerEnabledConfigurations; std::map<std::string, std::string> SpectreMitigation; + std::set<std::string> BuildSystemSourcesFilters; cmGlobalVisualStudio10Generator* const GlobalGenerator; cmLocalVisualStudio10Generator* const LocalGenerator; std::set<std::string> CSharpCustomCommandNames; diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index e727d22141..7f26fd8b23 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -13,6 +13,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" +#include "cmList.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -270,7 +271,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, if (cmValue argList = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) { - std::vector<std::string> arguments = cmExpandedList(*argList); + cmList arguments{ *argList }; if (!arguments.empty()) { xout.StartElement("CommandLineArguments"); @@ -290,7 +291,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, if (cmValue envList = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) { - std::vector<std::string> envs = cmExpandedList(*envList); + cmList envs{ *envList }; if (!envs.empty()) { xout.StartElement("EnvironmentVariables"); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 8dee5cc13c..0fd7461339 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -53,6 +53,7 @@ # include "cmMakefileProfilingData.h" #endif #include "cmJSONState.h" +#include "cmList.h" #include "cmMessenger.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -813,7 +814,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) } } else if (mode == "COMPILE"_s) { std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS"); - std::vector<std::string> includeDirs = cmExpandedList(includes); + cmList includeDirs{ includes }; this->GlobalGenerator->CreateGenerationObjects(); const auto& lg = this->GlobalGenerator->LocalGenerators[0]; @@ -829,7 +830,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) tgt->SetProperty("LINKER_LANGUAGE", language); std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES"); - std::vector<std::string> libList = cmExpandedList(libs); + cmList libList{ libs }; for (std::string const& lib : libList) { tgt->AddLinkLibrary(*mf, lib, GENERAL_LibraryType); } @@ -1026,7 +1027,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) CommandArgument{ "--check-build-system", CommandArgument::Values::Two, [](std::string const& value, cmake* state) -> bool { - std::vector<std::string> values = cmExpandedList(value); + cmList values{ value }; state->CheckBuildSystemArgument = values[0]; state->ClearBuildSystem = (atoi(values[1].c_str()) > 0); return true; @@ -2163,7 +2164,7 @@ struct SaveCacheEntry int cmake::HandleDeleteCacheVariables(const std::string& var) { - std::vector<std::string> argsSplit = cmExpandedList(var, true); + cmList argsSplit{ var, cmList::EmptyElements::Yes }; // erase the property to avoid infinite recursion this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", ""); if (this->GetIsInTryCompile()) { @@ -3140,9 +3141,8 @@ int cmake::CheckBuildSystem() } // If any byproduct of makefile generation is missing we must re-run. - std::vector<std::string> products; - mf.GetDefExpandList("CMAKE_MAKEFILE_PRODUCTS", products); - for (std::string const& p : products) { + cmList products{ mf.GetDefinition("CMAKE_MAKEFILE_PRODUCTS") }; + for (auto const& p : products) { if (!(cmSystemTools::FileExists(p) || cmSystemTools::FileIsSymlink(p))) { if (verbose) { cmSystemTools::Stdout( @@ -3153,10 +3153,10 @@ int cmake::CheckBuildSystem() } // Get the set of dependencies and outputs. - std::vector<std::string> depends; - std::vector<std::string> outputs; - if (mf.GetDefExpandList("CMAKE_MAKEFILE_DEPENDS", depends)) { - mf.GetDefExpandList("CMAKE_MAKEFILE_OUTPUTS", outputs); + cmList depends{ mf.GetDefinition("CMAKE_MAKEFILE_DEPENDS") }; + cmList outputs; + if (!depends.empty()) { + outputs.assign(mf.GetDefinition("CMAKE_MAKEFILE_OUTPUTS")); } if (depends.empty() || outputs.empty()) { // Not enough information was provided to do the test. Just rerun. @@ -3432,19 +3432,18 @@ void cmake::IssueMessage(MessageType t, std::string const& text, std::vector<std::string> cmake::GetDebugConfigs() { - std::vector<std::string> configs; + cmList configs; if (cmValue config_list = this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) { // Expand the specified list and convert to upper-case. - cmExpandList(*config_list, configs); - std::transform(configs.begin(), configs.end(), configs.begin(), - cmSystemTools::UpperCase); + configs.assign(*config_list); + configs.transform(cmList::TransformAction::TOUPPER); } // If no configurations were specified, use a default list. if (configs.empty()) { configs.emplace_back("DEBUG"); } - return configs; + return std::move(configs.data()); } int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index f4e602bf02..ad27443596 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -26,6 +26,7 @@ #include "cmConsoleBuf.h" #include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmMakefile.h" #include "cmMessageMetadata.h" #include "cmState.h" @@ -457,7 +458,7 @@ int do_build(int ac, char const* const* av) }; auto targetLambda = [&](std::string const& value) -> bool { if (!value.empty()) { - std::vector<std::string> values = cmExpandedList(value); + cmList values{ value }; for (auto const& v : values) { targets.emplace_back(v); if (v == "clean") { diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index a2a9e09cfc..9929e85905 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -3,6 +3,7 @@ #include "cmcmd.h" #include <functional> +#include <iterator> #include <cm/optional> #include <cmext/algorithm> @@ -14,6 +15,7 @@ #include "cmConsoleBuf.h" #include "cmDuration.h" #include "cmGlobalGenerator.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmQtAutoMocUic.h" @@ -342,10 +344,9 @@ int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */, { // Construct the iwyu command line by taking what was given // and adding all the arguments we give to the compiler. - std::vector<std::string> iwyu_cmd = cmExpandedList(runCmd, true); + cmList iwyu_cmd{ runCmd, cmList::EmptyElements::Yes }; cm::append(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end()); // Run the iwyu command line. Capture its stderr and hide its stdout. - // Ignore its return code because the tool always returns non-zero. std::string stdErr; int ret; if (!cmSystemTools::RunSingleCommand(iwyu_cmd, nullptr, &stdErr, &ret, @@ -359,14 +360,21 @@ int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */, std::cerr << "Warning: include-what-you-use reported diagnostics:\n" << stdErr << "\n"; } - // always return 0 we don't want to break the compile - return 0; + // Older versions of iwyu always returned a non-zero exit code, + // so ignore it unless the user has enabled errors. + auto has_error_opt = std::find_if( + iwyu_cmd.cbegin(), iwyu_cmd.cend(), + [](std::string const& opt) { return cmHasLiteralPrefix(opt, "--error"); }); + bool errors_enabled = has_error_opt != iwyu_cmd.cend() && + has_error_opt != iwyu_cmd.cbegin() && + *std::prev(has_error_opt) == "-Xiwyu"; + return errors_enabled ? ret : 0; } int HandleTidy(const std::string& runCmd, const std::string& sourceFile, const std::vector<std::string>& orig_cmd) { - std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true); + cmList tidy_cmd{ runCmd, cmList::EmptyElements::Yes }; tidy_cmd.push_back(sourceFile); for (auto const& arg : tidy_cmd) { @@ -416,7 +424,7 @@ int HandleLWYU(const std::string& runCmd, const std::string& sourceFile, { // Construct the ldd -r -u (link what you use lwyu) command line // ldd -u -r lwuy target - std::vector<std::string> lwyu_cmd = cmExpandedList(runCmd, true); + cmList lwyu_cmd{ runCmd, cmList::EmptyElements::Yes }; lwyu_cmd.push_back(sourceFile); // Run the lwyu check command line, currently ldd is expected. @@ -444,7 +452,7 @@ int HandleCppLint(const std::string& runCmd, const std::string& sourceFile, const std::vector<std::string>&) { // Construct the cpplint command line. - std::vector<std::string> cpplint_cmd = cmExpandedList(runCmd, true); + cmList cpplint_cmd{ runCmd, cmList::EmptyElements::Yes }; cpplint_cmd.push_back(sourceFile); // Run the cpplint command line. Capture its output. @@ -471,7 +479,7 @@ int HandleCppCheck(const std::string& runCmd, const std::string& sourceFile, const std::vector<std::string>& orig_cmd) { // Construct the cpplint command line. - std::vector<std::string> cppcheck_cmd = cmExpandedList(runCmd, true); + cmList cppcheck_cmd{ runCmd, cmList::EmptyElements::Yes }; // extract all the -D, -U, and -I options from the compile line for (auto const& opt : orig_cmd) { if (opt.size() > 2) { @@ -551,8 +559,8 @@ struct CoCompileJob int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args) { std::vector<CoCompileJob> jobs; - std::string sourceFile; // store --source= - std::vector<std::string> launchers; // store --launcher= + std::string sourceFile; // store --source= + cmList launchers; // store --launcher= // Default is to run the original command found after -- if the option // does not need to do that, it should be specified here, currently only @@ -585,7 +593,7 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args) if (cmHasLiteralPrefix(arg, "--source=")) { sourceFile = arg.substr(9); } else if (cmHasLiteralPrefix(arg, "--launcher=")) { - cmExpandList(arg.substr(11), launchers, true); + launchers.append(arg.substr(11), cmList::EmptyElements::Yes); } else { // if it was not a co-compiler or --source/--launcher then error std::cerr << "__run_co_compile given unknown argument: " << arg diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index c47266a75e..3bb2fd6b39 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -20,11 +20,19 @@ # else # define CM_NULL NULL # endif +# define CM_NAMESPACE_BEGIN namespace { +# define CM_NAMESPACE_END } +# define CM_LOCAL #else # define CM_CAST(TYPE, EXPR) (TYPE)(EXPR) # define CM_NULL NULL +# define CM_NAMESPACE_BEGIN +# define CM_NAMESPACE_END +# define CM_LOCAL static #endif +CM_NAMESPACE_BEGIN + /* Create map. */ typedef int (*MainFuncPointer)(int, char* []); /* NOLINT */ @@ -34,17 +42,17 @@ typedef struct /* NOLINT */ MainFuncPointer func; } functionMapEntry; -static functionMapEntry cmakeGeneratedFunctionMapEntries[] = { +CM_LOCAL const functionMapEntry cmakeGeneratedFunctionMapEntries[] = { @CMAKE_FUNCTION_TABLE_ENTRIES@ { CM_NULL, CM_NULL } /* NOLINT */ }; -static const int NumTests = CM_CAST(int, +CM_LOCAL const int NumTests = CM_CAST(int, sizeof(cmakeGeneratedFunctionMapEntries) / sizeof(functionMapEntry)) - 1; /* Allocate and create a lowercased copy of string (note that it has to be free'd manually) */ -static char* lowercase(const char* string) +CM_LOCAL char* lowercase(const char* string) { char *new_string; char *p; @@ -63,7 +71,7 @@ static char* lowercase(const char* string) return new_string; } -static int isTestSkipped(const char *name, int n_skipped_tests, char *skipped_tests[]) { +CM_LOCAL int isTestSkipped(const char *name, int n_skipped_tests, char *skipped_tests[]) { int i; for (i = 0; i < n_skipped_tests; i++) { if (strcmp(name, skipped_tests[i]) == 0) { @@ -74,6 +82,8 @@ static int isTestSkipped(const char *name, int n_skipped_tests, char *skipped_te return 0; } +CM_NAMESPACE_END + int main(int ac, char* av[]) { int i; diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps1.txt b/Tests/CMakeLib/testGccDepfileReader_data/deps1.txt index fd2679f41a..4207b58139 100644 --- a/Tests/CMakeLib/testGccDepfileReader_data/deps1.txt +++ b/Tests/CMakeLib/testGccDepfileReader_data/deps1.txt @@ -1,26 +1,26 @@ --RULES-- main.o --DEPENDENCIES-- -main.cpp +/usr/include/features.h /usr/include/stdc-predef.h /usr/include/stdio.h /usr/include/x86_64-linux-gnu/bits/libc-header-start.h -/usr/include/features.h -/usr/include/x86_64-linux-gnu/sys/cdefs.h -/usr/include/x86_64-linux-gnu/bits/wordsize.h /usr/include/x86_64-linux-gnu/bits/long-double.h -/usr/include/x86_64-linux-gnu/gnu/stubs.h -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h -/usr/lib/gcc/x86_64-linux-gnu/8/include/stddef.h -/usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/x86_64-linux-gnu/bits/types.h -/usr/include/x86_64-linux-gnu/bits/typesizes.h +/usr/include/x86_64-linux-gnu/bits/types/FILE.h +/usr/include/x86_64-linux-gnu/bits/types/__FILE.h +/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h /usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h -/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h -/usr/include/x86_64-linux-gnu/bits/types/__FILE.h -/usr/include/x86_64-linux-gnu/bits/types/FILE.h -/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h /usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h +/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h +/usr/include/x86_64-linux-gnu/bits/typesizes.h +/usr/include/x86_64-linux-gnu/bits/wordsize.h +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h +/usr/include/x86_64-linux-gnu/gnu/stubs.h +/usr/include/x86_64-linux-gnu/sys/cdefs.h +/usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h +/usr/lib/gcc/x86_64-linux-gnu/8/include/stddef.h +main.cpp diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps3.txt b/Tests/CMakeLib/testGccDepfileReader_data/deps3.txt index 448f69c1e5..8d82c60d44 100644 --- a/Tests/CMakeLib/testGccDepfileReader_data/deps3.txt +++ b/Tests/CMakeLib/testGccDepfileReader_data/deps3.txt @@ -1,11 +1,11 @@ --RULES-- main.o --DEPENDENCIES-- -main.cpp -foo#bar.h -foo\#bar.h foo bar.h +foo#bar.h +foo$bar.h foo\ bar.h +foo\#bar.h foo\\ bar.h foo\\\\ -foo$bar.h +main.cpp diff --git a/Tests/CMakeLib/testList.cxx b/Tests/CMakeLib/testList.cxx index 7294be0b31..f6ec7208ea 100644 --- a/Tests/CMakeLib/testList.cxx +++ b/Tests/CMakeLib/testList.cxx @@ -8,7 +8,7 @@ #include <utility> #include <vector> -#include <cm/string_view> +#include <cmext/string_view> #include "cmList.h" @@ -42,7 +42,7 @@ bool testConstructors() } { cmList list1{ "aa", "bb" }; - cmList list2("aa;bb"); + cmList list2("aa;bb"_s); if (list1.size() != 2 || list2.size() != 2 || list1 != list2) { result = false; @@ -174,7 +174,7 @@ bool testAssign() { cmList list{ "cc", "dd" }; - list = "aa;bb"; + list = "aa;bb"_s; if (list.size() != 2) { result = false; } @@ -195,7 +195,7 @@ bool testConversions() bool result = true; { - cmList list("a;b;c"); + cmList list("a;b;c"_s); std::string s = list.to_string(); if (s != "a;b;c") { @@ -203,7 +203,7 @@ bool testConversions() } } { - cmList list("a;b;c"); + cmList list("a;b;c"_s); std::vector<std::string> v = list; if (list.size() != 3 || v.size() != 3) { @@ -211,7 +211,7 @@ bool testConversions() } } { - cmList list("a;b;c"); + cmList list("a;b;c"_s); std::vector<std::string> v = std::move(list); // Microsoft compiler is not able to handle correctly the move semantics @@ -221,7 +221,7 @@ bool testConversions() } } { - cmList list("a;b;c"); + cmList list("a;b;c"_s); std::vector<std::string> v; // compiler is not able to select the cmList conversion operator @@ -247,20 +247,20 @@ bool testAccess() { cmList list{ "a", "b", "c" }; - if (list.at(1) != "b") { + if (list.get_item(1) != "b") { result = false; } } { cmList list{ "a", "b", "c" }; - if (list.at(-3) != "a") { + if (list.get_item(-3) != "a") { result = false; } } { try { cmList list{ "a", "b", "c" }; - if (list.at(4) != "a") { + if (list.get_item(4) != "a") { result = false; } } catch (std::out_of_range&) { @@ -269,7 +269,7 @@ bool testAccess() { try { cmList list{ "a", "b", "c" }; - if (list.at(-4) != "a") { + if (list.get_item(-4) != "a") { result = false; } } catch (std::out_of_range&) { @@ -342,7 +342,7 @@ bool testModifiers() { cmList list{ "1;2;3;4;5" }; - auto it = list.insert(list.begin() + 2, "6;7;8"); + auto it = list.insert(list.begin() + 2, "6;7;8"_s); if (list.size() != 8 || list.to_string() != "1;2;6;7;8;3;4;5") { result = false; } @@ -354,7 +354,7 @@ bool testModifiers() cmList list{ "1;2;3;4;5" }; auto it = - list.insert(list.begin() + 2, "6;7;8", cmList::ExpandElements::No); + list.insert(list.begin() + 2, "6;7;8"_s, cmList::ExpandElements::No); if (list.size() != 6 || list.to_string() != "1;2;6;7;8;3;4;5") { result = false; } @@ -479,7 +479,7 @@ bool testRemoveItems() bool result = true; { - cmList list("a;b;c;d;e;f;g;h"); + cmList list("a;b;c;d;e;f;g;h"_s); list.remove_items({ 1, 3, 5 }); @@ -488,7 +488,7 @@ bool testRemoveItems() } } { - cmList list("a;b;c;b;a;d;e;f"); + cmList list("a;b;c;b;a;d;e;f"_s); list.remove_items({ "a", "b", "h" }); @@ -497,7 +497,7 @@ bool testRemoveItems() } } { - cmList list("a;b;c;d;e;f;g;h"); + cmList list("a;b;c;d;e;f;g;h"_s); std::vector<cmList::index_type> remove{ 1, 3, 5 }; list.remove_items(remove.begin(), remove.end()); @@ -507,7 +507,7 @@ bool testRemoveItems() } } { - cmList list("a;b;c;b;a;d;e;f"); + cmList list("a;b;c;b;a;d;e;f"_s); std::vector<std::string> remove{ "b", "a", "h" }; list.remove_items(remove.begin(), remove.end()); @@ -529,7 +529,7 @@ bool testRemoveDuplicates() bool result = true; { - cmList list("b;c;b;a;a;c;b;a;c;b"); + cmList list("b;c;b;a;a;c;b;a;c;b"_s); list.remove_duplicates(); @@ -803,7 +803,7 @@ bool testStaticModifiers() { std::vector<std::string> v{ "a", "b", "c" }; - cmList::assign("d;e", v); + cmList::assign(v, "d;e"_s); if (v.size() != 2 || v[0] != "d" || v[1] != "e") { result = false; @@ -811,7 +811,7 @@ bool testStaticModifiers() } { std::vector<std::string> v{ "a", "b", "c" }; - cmList::append("d;;e", v); + cmList::append(v, "d;;e"_s); if (v.size() != 5 || v[3] != "d" || v[4] != "e") { result = false; @@ -819,7 +819,7 @@ bool testStaticModifiers() } { std::vector<std::string> v{ "a", "b", "c" }; - cmList::append("d;;e", v, cmList::EmptyElements::Yes); + cmList::append(v, "d;;e"_s, cmList::EmptyElements::Yes); if (v.size() != 6 || v[3] != "d" || !v[4].empty() || v[5] != "e") { result = false; @@ -827,7 +827,7 @@ bool testStaticModifiers() } { std::vector<std::string> v{ "a", "b", "c" }; - cmList::prepend("d;e", v); + cmList::prepend(v, "d;e"_s); if (v.size() != 5 || v[0] != "d" || v[1] != "e") { result = false; @@ -835,7 +835,7 @@ bool testStaticModifiers() } { std::vector<std::string> v{ "a", "b", "c" }; - cmList::prepend("d;;e", v, cmList::EmptyElements::Yes); + cmList::prepend(v, "d;;e"_s, cmList::EmptyElements::Yes); if (v.size() != 6 || v[0] != "d" || !v[1].empty() || v[2] != "e") { result = false; @@ -843,7 +843,7 @@ bool testStaticModifiers() } { std::string list{ "a;b;c" }; - cmList::append("d;e", list); + cmList::append(list, "d;e"_s); if (list != "a;b;c;d;e") { result = false; @@ -851,7 +851,7 @@ bool testStaticModifiers() } { std::string list; - cmList::append("d;e", list); + cmList::append(list, "d;e"_s); if (list != "d;e") { result = false; @@ -859,7 +859,7 @@ bool testStaticModifiers() } { std::string list{ "a;b;c" }; - cmList::append("", list); + cmList::append(list, ""); if (list != "a;b;c;") { result = false; @@ -868,7 +868,7 @@ bool testStaticModifiers() { std::string list{ "a;b;c" }; std::vector<std::string> v{ "d", "e" }; - cmList::append(v.begin(), v.end(), list); + cmList::append(list, v.begin(), v.end()); if (list != "a;b;c;d;e") { result = false; @@ -877,7 +877,7 @@ bool testStaticModifiers() { std::string list{ "a;b;c" }; std::vector<std::string> v; - cmList::append(v.begin(), v.end(), list); + cmList::append(list, v.begin(), v.end()); if (list != "a;b;c") { result = false; @@ -886,7 +886,7 @@ bool testStaticModifiers() { std::string list; std::vector<std::string> v{ "d", "e" }; - cmList::append(v.begin(), v.end(), list); + cmList::append(list, v.begin(), v.end()); if (list != "d;e") { result = false; @@ -894,7 +894,7 @@ bool testStaticModifiers() } { std::string list{ "a;b;c" }; - cmList::prepend("d;e", list); + cmList::prepend(list, "d;e"); if (list != "d;e;a;b;c") { result = false; @@ -902,7 +902,7 @@ bool testStaticModifiers() } { std::string list; - cmList::prepend("d;e", list); + cmList::prepend(list, "d;e"); if (list != "d;e") { result = false; @@ -910,7 +910,7 @@ bool testStaticModifiers() } { std::string list{ "a;b;c" }; - cmList::prepend("", list); + cmList::prepend(list, ""); if (list != ";a;b;c") { result = false; @@ -919,7 +919,7 @@ bool testStaticModifiers() { std::string list{ "a;b;c" }; std::vector<std::string> v{ "d", "e" }; - cmList::prepend(v.begin(), v.end(), list); + cmList::prepend(list, v.begin(), v.end()); if (list != "d;e;a;b;c") { result = false; @@ -928,7 +928,7 @@ bool testStaticModifiers() { std::string list{ "a;b;c" }; std::vector<std::string> v; - cmList::prepend(v.begin(), v.end(), list); + cmList::prepend(list, v.begin(), v.end()); if (list != "a;b;c") { result = false; @@ -937,7 +937,7 @@ bool testStaticModifiers() { std::string list; std::vector<std::string> v{ "d", "e" }; - cmList::prepend(v.begin(), v.end(), list); + cmList::prepend(list, v.begin(), v.end()); if (list != "d;e") { result = false; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e92d1c1c09..e3b5ec41d8 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -986,6 +986,30 @@ if(BUILD_TESTING) endif() endif() + # On Windows run the CPackInnoSetupGenerator test + if(WIN32 AND CMake_TEST_CPACK_INNOSETUP) + add_test(CPackInnoSetupGenerator ${CMAKE_CTEST_COMMAND} + -C \${CTEST_CONFIGURATION_TYPE} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/CPackInnoSetupGenerator" + "${CMake_BINARY_DIR}/Tests/CPackInnoSetupGenerator" + ${build_generator_args} + --build-project CPackInnoSetupGenerator + --build-options + --test-command ${CMAKE_CMAKE_COMMAND} + "-DCPackInnoSetupGenerator_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/CPackInnoSetupGenerator" + "-Dconfig=\${CTEST_CONFIGURATION_TYPE}" + -P "${CMake_SOURCE_DIR}/Tests/CPackInnoSetupGenerator/RunCPackVerifyResult.cmake") + + set_property(TEST CPackInnoSetupGenerator PROPERTY + ATTACHED_FILES_ON_FAIL + "${CMake_BINARY_DIR}/Tests/CPackInnoSetupGenerator/_CPack_Packages/win32/INNOSETUP/ISCCOutput.log") + + set_property(TEST CPackInnoSetupGenerator PROPERTY + ATTACHED_FILES + "${CMake_BINARY_DIR}/Tests/CPackInnoSetupGenerator/_CPack_Packages/win32/INNOSETUP/ISScript.iss") + endif() + # On Windows run the CPackNSISGenerator test # if the nsis is available if(WIN32 AND NSIS_MAKENSIS_EXECUTABLE) diff --git a/Tests/CPackInnoSetupGenerator/CMakeLists.txt b/Tests/CPackInnoSetupGenerator/CMakeLists.txt new file mode 100644 index 0000000000..bca0ad6cd7 --- /dev/null +++ b/Tests/CPackInnoSetupGenerator/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.13) + +project(CPackInnoSetupGenerator VERSION 42.0 HOMEPAGE_URL "https://www.example.com") + +add_executable(hello main.c) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/empty) + +install(TARGETS hello DESTINATION / COMPONENT application) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/empty DESTINATION / COMPONENT extras) +install(FILES my_bitmap.bmp DESTINATION awesome COMPONENT extras) +install(FILES my_file.txt DESTINATION / COMPONENT hidden_component) +install(FILES my_file.txt DESTINATION / COMPONENT hidden_component2) + +set(CPACK_GENERATOR "INNOSETUP") + +set(CPACK_PACKAGE_NAME "Hello, World!") # Test constant escape (like {cm:...}, see code documentation) +set(CPACK_PACKAGE_VENDOR "Sheldon Cooper") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "hello_world") +set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "hello_world") +set(CPACK_PACKAGE_FILE_NAME "hello_world_setup") +set(CPACK_SYSTEM_NAME "win32") +set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/my_bitmap.bmp") +set(CPACK_VERBATIM_VARIABLES ON) +set(CPACK_PACKAGE_EXECUTABLES "hello" "Hello, World!") +set(CPACK_CREATE_DESKTOP_LINKS hello) + +set(CPACK_INNOSETUP_INSTALL_ROOT "{autopf}\\Sheldon Cooper") +set(CPACK_INNOSETUP_PROGRAM_MENU_FOLDER ".") +set(CPACK_INNOSETUP_IGNORE_LICENSE_PAGE ON) +set(CPACK_INNOSETUP_IGNORE_README_PAGE OFF) # Test if only readme page is shown +set(CPACK_INNOSETUP_SETUP_AppComments ON) # Test if CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT works +set(CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS "extras/empty" + "Name: \"{userdocs}\\empty\"\; Check: ReturnTrue\; Components: accessories\\extras") +set(CPACK_INNOSETUP_MENU_LINKS "https://www.example.com" "Web" + "my_file.txt" "Text") +set(CPACK_INNOSETUP_RUN_EXECUTABLES hello) +set(CPACK_INNOSETUP_CREATE_UNINSTALL_LINK ON) +# Test if this macro is available in the code file below containing the check function +set(CPACK_INNOSETUP_DEFINE_PascalMacro "end;") +set(CPACK_INNOSETUP_CODE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/Code.pas") +set(CPACK_INNOSETUP_EXECUTABLE "ISCC.exe") + +include(CPackComponent) + +cpack_add_install_type(basic DISPLAY_NAME "Basic installation") +cpack_add_install_type(full DISPLAY_NAME "\"Large\" installation") # Test double quote syntax +cpack_add_component_group(accessories DISPLAY_NAME "Accessories") + +cpack_add_component(application DISPLAY_NAME "Application" INSTALL_TYPES basic full REQUIRED) +cpack_add_component(extras DISPLAY_NAME "Additional components" INSTALL_TYPES full GROUP accessories) +cpack_add_component(hidden_component HIDDEN) +cpack_add_component(hidden_component2 HIDDEN DISABLED) +set(CPACK_INNOSETUP_extras_INSTALL_DIRECTORY "{userdocs}") + +include(CPack) diff --git a/Tests/CPackInnoSetupGenerator/Code.pas b/Tests/CPackInnoSetupGenerator/Code.pas new file mode 100644 index 0000000000..d96d82f2df --- /dev/null +++ b/Tests/CPackInnoSetupGenerator/Code.pas @@ -0,0 +1,4 @@ +function ReturnTrue(): Boolean; +begin + Result := true; +{#PascalMacro} diff --git a/Tests/CPackInnoSetupGenerator/RunCPackVerifyResult.cmake b/Tests/CPackInnoSetupGenerator/RunCPackVerifyResult.cmake new file mode 100644 index 0000000000..72a26ee754 --- /dev/null +++ b/Tests/CPackInnoSetupGenerator/RunCPackVerifyResult.cmake @@ -0,0 +1,136 @@ +message(STATUS "=============================================================") +message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") +message(STATUS "") + +if(NOT CPackInnoSetupGenerator_BINARY_DIR) + message(FATAL_ERROR "CPackInnoSetupGenerator_BINARY_DIR not set") +endif() + +message(STATUS "CMAKE_COMMAND: ${CMAKE_COMMAND}") +message(STATUS "CMAKE_CPACK_COMMAND: ${CMAKE_CPACK_COMMAND}") +message(STATUS "CPackInnoSetupGenerator_BINARY_DIR: ${CPackInnoSetupGenerator_BINARY_DIR}") + +if(config) + set(_C_config -C ${config}) +endif() + +execute_process(COMMAND "${CMAKE_CPACK_COMMAND}" + ${_C_config} + RESULT_VARIABLE CPack_result + OUTPUT_VARIABLE CPack_output + ERROR_VARIABLE CPack_output + WORKING_DIRECTORY "${CPackInnoSetupGenerator_BINARY_DIR}") + +if(CPack_result) + message(FATAL_ERROR "CPack execution went wrong!, Output: ${CPack_output}") +else () + message(STATUS "Output: ${CPack_output}") +endif() + +file(GLOB project_file "${CPackInnoSetupGenerator_BINARY_DIR}/_CPack_Packages/win32/INNOSETUP/ISScript.iss") +file(GLOB installer_file "${CPackInnoSetupGenerator_BINARY_DIR}/_CPack_Packages/win32/INNOSETUP/hello_world_setup.exe") + +message(STATUS "Project file: '${project_file}'") +message(STATUS "Installer file: '${installer_file}'") + +if(NOT project_file) + message(FATAL_ERROR "Project file does not exist") +endif() + +if(NOT installer_file) + message(FATAL_ERROR "Installer file does not exist") +endif() + +# Test if the correct registry key is set +file(STRINGS "${project_file}" results REGEX "^AppId=hello_world$") +if(results STREQUAL "") + message(FATAL_ERROR "CPACK_PACKAGE_INSTALL_REGISTRY_KEY doesn't match AppId") +endif() + +# Test if only readme page is shown +file(STRINGS "${project_file}" results REGEX "^LicenseFile=") +file(STRINGS "${project_file}" results2 REGEX "^InfoBeforeFile=") +if(NOT results STREQUAL "" OR results2 STREQUAL "") + message(FATAL_ERROR "Erroneous output with license and readme files") +endif() + +# Test if classic style is used by default +file(STRINGS "${project_file}" results REGEX "compiler:SetupClassicIcon\\.ico") +file(STRINGS "${project_file}" results2 REGEX "compiler:WizClassicImage\\.bmp") +if(results STREQUAL "" OR results2 STREQUAL "") + message(FATAL_ERROR "Images of classic style not used") +endif() + +# Test if the top-level start menu folder is used +file(STRINGS "${project_file}" results REGEX "{autoprograms}") +file(STRINGS "${project_file}" results2 REGEX "{group}") +if(results STREQUAL "" OR NOT results2 STREQUAL "") + message(FATAL_ERROR "Top-level start menu folder not used") +endif() + +# Test CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT +file(STRINGS "${project_file}" results REGEX "^AppComments=yes$") +if(results STREQUAL "") + message(FATAL_ERROR "CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT doesn't convert booleans") +endif() + +# Test the custom installation rule +file(STRINGS "${project_file}" results REGEX "^Name: \"{userdocs}\\\\empty\"; Check: ReturnTrue; Components: accessories\\\\extras$") +if(results STREQUAL "") + message(FATAL_ERROR "Custom installation rule not found or incomplete") +endif() + +# Test if an uninstall shortcut has been created +file(STRINGS "${project_file}" results REGEX "{uninstallexe}") +if(results STREQUAL "") + message(FATAL_ERROR "No uninstall shortcut created") +endif() + +# Test CPACK_INNOSETUP_<compName>_INSTALL_DIRECTORY +file(STRINGS "${project_file}" results REGEX "{app}.*Components: accessories\\\\extras") +if(NOT results STREQUAL "") + message(FATAL_ERROR "Component not in custom install directory") +endif() + +# Test if component names are nested correctly +file(STRINGS "${project_file}" results REGEX "Components:.* extras") +if(NOT results STREQUAL "") + message(FATAL_ERROR "Component names must contain their parent groups according to the documentation") +endif() + +# Test if custom installation type exists +file(STRINGS "${project_file}" results REGEX "Flags: .*iscustom") +if(results STREQUAL "") + message(FATAL_ERROR "Custom installation type doesn't exist") +endif() + +# Test if hidden components are processed but not displayed +file(STRINGS "${project_file}" results REGEX "Source:.+hidden_component\\\\my_file\\.txt") +file(STRINGS "${project_file}" results2 REGEX "Name: \"hidden_component\"") +if(results STREQUAL "" OR NOT results2 STREQUAL "") + message(FATAL_ERROR "Hidden component displayed or one of its files ignored") +endif() + +# Test if disabled and hidden components are ignored at all +file(STRINGS "${project_file}" results REGEX "Source:.+hidden_component2\\\\my_file\\.txt") +if(NOT results STREQUAL "") + message(FATAL_ERROR "Disabled and hidden component not ignored") +endif() + +# Test if required components ignore their installation types +file(STRINGS "${project_file}" results REGEX "Types: (basic|full|custom|basic full|full basic|basic custom|full custom); Flags: fixed") +if(NOT results STREQUAL "") + message(FATAL_ERROR "Required components don't ignore their installation types") +endif() + +# Test constant escape (should contain Hello%2c World!) +file(STRINGS "${project_file}" results REGEX "Hello%2c World!") +if(results STREQUAL "") + message(FATAL_ERROR "The comma character isn't escaped to %2c") +endif() + +# Test double quote syntax +file(STRINGS "${project_file}" results REGEX "\"\"Large\"\"") +if(results STREQUAL "") + message(FATAL_ERROR "The quote character isn't escaped correctly") +endif() diff --git a/Tests/CPackInnoSetupGenerator/main.c b/Tests/CPackInnoSetupGenerator/main.c new file mode 100644 index 0000000000..413899c807 --- /dev/null +++ b/Tests/CPackInnoSetupGenerator/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main() +{ + printf("Hello, World!\n"); + return 42; +} diff --git a/Tests/CPackInnoSetupGenerator/my_bitmap.bmp b/Tests/CPackInnoSetupGenerator/my_bitmap.bmp Binary files differnew file mode 100644 index 0000000000..d0e562fb37 --- /dev/null +++ b/Tests/CPackInnoSetupGenerator/my_bitmap.bmp diff --git a/Tests/CPackInnoSetupGenerator/my_file.txt b/Tests/CPackInnoSetupGenerator/my_file.txt new file mode 100644 index 0000000000..8ab686eafe --- /dev/null +++ b/Tests/CPackInnoSetupGenerator/my_file.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c index b990e53258..c696c83f3e 100644 --- a/Tests/CompileFeatures/default_dialect.c +++ b/Tests/CompileFeatures/default_dialect.c @@ -20,7 +20,8 @@ # error Buildsystem error # endif # if defined(__STDC_VERSION__) && \ - !(defined(__SUNPRO_C) && __STDC_VERSION__ == 199409L) + !(__STDC_VERSION__ == 199409L && \ + (defined(__INTEL_COMPILER) || defined(__SUNPRO_C))) # error Unexpected __STDC_VERSION__ definition # endif #endif diff --git a/Tests/Cuda/Toolkit/CMakeLists.txt b/Tests/Cuda/Toolkit/CMakeLists.txt index b67aa3279f..8432b71ff1 100644 --- a/Tests/Cuda/Toolkit/CMakeLists.txt +++ b/Tests/Cuda/Toolkit/CMakeLists.txt @@ -16,8 +16,22 @@ message(STATUS "CUDAToolkit_VERSION_PATCH: ${CUDAToolkit_VERSION_PATCH}") message(STATUS "CUDAToolkit_BIN_DIR: ${CUDAToolkit_BIN_DIR}") message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}") message(STATUS "CUDAToolkit_LIBRARY_DIR: ${CUDAToolkit_LIBRARY_DIR}") +message(STATUS "CUDAToolkit_LIBRARY_ROOT: ${CUDAToolkit_LIBRARY_ROOT}") message(STATUS "CUDAToolkit_NVCC_EXECUTABLE ${CUDAToolkit_NVCC_EXECUTABLE}") +set(should_exist + CUDAToolkit_BIN_DIR + CUDAToolkit_INCLUDE_DIRS + CUDAToolkit_LIBRARY_DIR + CUDAToolkit_LIBRARY_ROOT + ) +foreach (cuda_loc_var IN LISTS should_exist) + if(NOT EXISTS "${${cuda_loc_var}}") + message(FATAL_ERROR "${cuda_loc_var} variable is expected to be set to valid path") + endif() +endforeach() + + set(cuda_libs cudart cuda_driver cublas cufft cufftw curand cusolver cusparse) if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.1) list(APPEND cuda_libs cublasLt) diff --git a/Tests/FindX11/Test/CMakeLists.txt b/Tests/FindX11/Test/CMakeLists.txt index e39ffb1eff..3312f6f772 100644 --- a/Tests/FindX11/Test/CMakeLists.txt +++ b/Tests/FindX11/Test/CMakeLists.txt @@ -32,16 +32,38 @@ test_x11_component(x11_components Xau) test_x11_component(x11_components Xaw) test_x11_component(x11_components xcb) test_x11_component(x11_components X11_xcb) +test_x11_component(x11_components xcb_composite) test_x11_component(x11_components xcb_cursor) +test_x11_component(x11_components xcb_damage) +test_x11_component(x11_components xcb_dpms) +test_x11_component(x11_components xcb_dri2) +test_x11_component(x11_components xcb_dri3) +test_x11_component(x11_components xcb_errors) +test_x11_component(x11_components xcb_ewmh) +test_x11_component(x11_components xcb_glx) test_x11_component(x11_components xcb_icccm) +test_x11_component(x11_components xcb_image) +test_x11_component(x11_components xcb_keysyms) +test_x11_component(x11_components xcb_present) test_x11_component(x11_components xcb_randr) +test_x11_component(x11_components xcb_record) +test_x11_component(x11_components xcb_render) +test_x11_component(x11_components xcb_render_util) +test_x11_component(x11_components xcb_res) +test_x11_component(x11_components xcb_screensaver) test_x11_component(x11_components xcb_shape) +test_x11_component(x11_components xcb_shm) +test_x11_component(x11_components xcb_sync) test_x11_component(x11_components xcb_util) +test_x11_component(x11_components xcb_xf86dri) test_x11_component(x11_components xcb_xfixes) +test_x11_component(x11_components xcb_xinerama) +test_x11_component(x11_components xcb_xinput) +test_x11_component(x11_components xcb_xkb) test_x11_component(x11_components xcb_xrm) test_x11_component(x11_components xcb_xtest) -test_x11_component(x11_components xcb_keysyms) -test_x11_component(x11_components xcb_xkb) +test_x11_component(x11_components xcb_xvmc) +test_x11_component(x11_components xcb_xv) test_x11_component(x11_components Xcomposite) test_x11_component(x11_components Xdamage) test_x11_component(x11_components Xdmcp) @@ -79,13 +101,38 @@ foreach(lib Xaw xcb X11_xcb + xcb_composite xcb_cursor + xcb_damage + xcb_dpms + xcb_dri2 + xcb_dri3 + xcb_errors + xcb_ewmh + xcb_glx xcb_icccm + xcb_image + xcb_keysyms + xcb_present xcb_randr + xcb_record + xcb_render + xcb_render_util + xcb_res + xcb_screensaver xcb_shape + xcb_shm + xcb_sync xcb_util + xcb_xf86dri xcb_xfixes + xcb_xinerama + xcb_xinput + xcb_xkb xcb_xrm + xcb_xtest + xcb_xvmc + xcb_xv Xcomposite Xdamage Xdmcp diff --git a/Tests/FindX11/Test/main.c b/Tests/FindX11/Test/main.c index 5240de0f68..2542145e5f 100644 --- a/Tests/FindX11/Test/main.c +++ b/Tests/FindX11/Test/main.c @@ -326,7 +326,7 @@ static void test_Xaw(void) #endif -#ifdef HAVE_xcb +#ifdef HAVE_X11_xcb # include <xcb/xcb.h> static void test_xcb(void) @@ -336,24 +336,216 @@ static void test_xcb(void) xcb_disconnect(connection); } -# ifdef HAVE_xcb_cursor -# include <xcb/xcb_cursor.h> +#endif + +#ifdef HAVE_X11_xcb_composite +# include <xcb/composite.h> +# include <xcb/xcb.h> + +static void test_xcb_composite(void) +{ + xcb_connection_t* connection = xcb_connect(NULL, NULL); + xcb_composite_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_cursor +# include <xcb/xcb.h> +# include <xcb/xcb_cursor.h> static void test_xcb_cursor(void) { int screen_nbr; xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); - xcb_screen_t* screen = xcb_aux_get_screen(conn, screen_nbr); + xcb_screen_iterator_t screens = + xcb_setup_roots_iterator(xcb_get_setup(connection)); xcb_cursor_context_t* ctx; - xcb_cursor_context_new(connection, screen, &ctx); + xcb_cursor_context_new(connection, screens.data, &ctx); xcb_cursor_context_free(ctx); xcb_disconnect(connection); } -# endif +#endif -# ifdef HAVE_xcb_randr -# include <xcb/randr.h> +#ifdef HAVE_X11_xcb_damage +# include <xcb/damage.h> +# include <xcb/xcb.h> + +static void test_xcb_damage(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_damage_query_version_cookie_t cookie = + xcb_damage_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_dpms +# include <xcb/dpms.h> +# include <xcb/xcb.h> + +static void test_xcb_dpms(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_dpms_get_version_cookie_t cookie = + xcb_dpms_get_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_dri2 +# include <xcb/dri2.h> +# include <xcb/xcb.h> + +static void test_xcb_dri2(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_dri2_query_version_cookie_t cookie = + xcb_dri2_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_dri3 +# include <xcb/dri3.h> +# include <xcb/xcb.h> + +static void test_xcb_dri3(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_dri3_query_version_cookie_t cookie = + xcb_dri3_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_errors +# include <xcb/xcb.h> +# include <xcb/xcb_errors.h> + +static void test_xcb_errors(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_errors_context_t* context; + xcb_errors_context_new(connection, &context); + xcb_errors_context_free(context); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_ewmh +# include <xcb/xcb.h> +# include <xcb/xcb_ewmh.h> + +static void test_xcb_ewmh(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_ewmh_connection_t ewmh_connection; + xcb_intern_atom_cookie_t* cookie = + xcb_ewmh_init_atoms(connection, &ewmh_connection); + xcb_ewmh_init_atoms_replies(&ewmh_connection, cookie, NULL); + xcb_ewmh_connection_wipe(&ewmh_connection); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_glx +# include <xcb/glx.h> +# include <xcb/xcb.h> + +static void test_xcb_glx(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_glx_query_version_cookie_t cookie = + xcb_glx_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_icccm +# include <xcb/xcb.h> +# include <xcb/xcb_icccm.h> + +static void test_xcb_icccm(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_window_t root = + xcb_setup_roots_iterator(xcb_get_setup(connection)).data->root; + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name(connection, root); + xcb_icccm_get_text_property_reply_t reply; + xcb_icccm_get_wm_name_reply(connection, cookie, &reply, NULL); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_image +# include <xcb/xcb.h> +# include <xcb/xcb_image.h> + +static void test_xcb_image(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + // xcb_image is too convoluted/undocumented to make an + // actually working example, apologies :) + xcb_image_create(0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_keysyms +# include <xcb/xcb.h> +# include <xcb/xcb_keysyms.h> + +static void test_xcb_keysyms(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_key_symbols_t* symbols = xcb_key_symbols_alloc(connection); + if (symbols != NULL) + xcb_key_symbols_free(symbols); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_present +# include <xcb/present.h> +# include <xcb/xcb.h> + +static void test_xcb_present(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_present_query_version_cookie_t cookie = + xcb_present_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_randr +# include <xcb/randr.h> +# include <xcb/xcb.h> static void test_xcb_randr(void) { @@ -364,10 +556,86 @@ static void test_xcb_randr(void) xcb_disconnect(connection); } -# endif +#endif + +#ifdef HAVE_X11_xcb_record +# include <xcb/record.h> +# include <xcb/xcb.h> + +static void test_xcb_record(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_record_query_version_cookie_t cookie = + xcb_record_query_version(connection, 0, 0); + xcb_disconnect(connection); +} -# ifdef HAVE_xcb_shape -# include <xcb/shape.h> +#endif + +#ifdef HAVE_X11_xcb_render +# include <xcb/render.h> +# include <xcb/xcb.h> + +static void test_xcb_render(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_render_query_version_cookie_t cookie = + xcb_render_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_render_util +# include <xcb/xcb.h> +# include <xcb/xcb_renderutil.h> + +static void test_xcb_render_util(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + const xcb_render_query_version_reply_t* cookie = + xcb_render_util_query_version(connection); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_res +# include <xcb/res.h> +# include <xcb/xcb.h> + +static void test_xcb_res(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_res_query_version_cookie_t cookie = + xcb_res_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_screensaver +# include <xcb/screensaver.h> +# include <xcb/xcb.h> + +static void test_xcb_screensaver(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_screensaver_query_version_cookie_t cookie = + xcb_screensaver_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_shape +# include <xcb/shape.h> +# include <xcb/xcb.h> static void test_xcb_shape(void) { @@ -378,10 +646,39 @@ static void test_xcb_shape(void) xcb_disconnect(connection); } -# endif +#endif + +#ifdef HAVE_X11_xcb_shm +# include <xcb/shm.h> +# include <xcb/xcb.h> + +static void test_xcb_shm(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(connection); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_sync +# include <xcb/sync.h> +# include <xcb/xcb.h> + +static void test_xcb_sync(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_sync_initialize_cookie_t cookie = xcb_sync_initialize(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif -# ifdef HAVE_xcb_util -# include <xcb/xcb_aux.h> +#ifdef HAVE_X11_xcb_util +# include <xcb/xcb.h> +# include <xcb/xcb_aux.h> static void test_xcb_util(void) { @@ -391,10 +688,26 @@ static void test_xcb_util(void) xcb_disconnect(connection); } -# endif +#endif + +#ifdef HAVE_X11_xcb_xf86dri +# include <xcb/xcb.h> +# include <xcb/xf86dri.h> + +static void test_xcb_xf86dri(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_xf86dri_query_version_cookie_t cookie = + xcb_xf86dri_query_version(connection); + xcb_disconnect(connection); +} + +#endif -# ifdef HAVE_xcb_xfixes -# include <xcb/xcb_xfixes.h> +#ifdef HAVE_X11_xcb_xfixes +# include <xcb/xcb.h> +# include <xcb/xfixes.h> static void test_xcb_xfixes(void) { @@ -404,10 +717,56 @@ static void test_xcb_xfixes(void) xcb_disconnect(connection); } -# endif +#endif + +#ifdef HAVE_X11_xcb_xinerama +# include <xcb/xcb.h> +# include <xcb/xinerama.h> + +static void test_xcb_xinerama(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_xinerama_query_version_cookie_t cookie = + xcb_xinerama_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_xinput +# include <xcb/xcb.h> +# include <xcb/xinput.h> + +static void test_xcb_xinput(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_input_xi_query_version_cookie_t cookie = + xcb_input_xi_query_version(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif + +#ifdef HAVE_X11_xcb_xkb +# include <xcb/xcb.h> +# include <xcb/xkb.h> + +static void test_xcb_xkb(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_xkb_use_extension_cookie_t cookie = + xcb_xkb_use_extension(connection, 0, 0); + xcb_disconnect(connection); +} + +#endif -# ifdef HAVE_xcb_xrm -# include <xcb/xcb_xrm.h> +#ifdef HAVE_X11_xcb_xrm +# include <xcb/xcb.h> +# include <xcb/xcb_xrm.h> static void test_xcb_xrm(void) { @@ -418,10 +777,11 @@ static void test_xcb_xrm(void) xcb_disconnect(connection); } -# endif +#endif -# ifdef HAVE_xcb_xtest -# include <xcb/xtest.h> +#ifdef HAVE_X11_xcb_xtest +# include <xcb/xcb.h> +# include <xcb/xtest.h> static void test_xcb_xtest(void) { @@ -431,22 +791,33 @@ static void test_xcb_xtest(void) xcb_disconnect(connection); } -# endif +#endif -# ifdef HAVE_xcb_keysyms -# include <xcb/xcb_keysyms.h> +#ifdef HAVE_X11_xcb_xvmc +# include <xcb/xcb.h> +# include <xcb/xvmc.h> -static void test_xcb_keysyms(void) +static void test_xcb_xvmc(void) { int screen_nbr; xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); - xcb_key_symbols_t* symbols = xcb_key_symbols_alloc(connection); - if (symbols != NULL) - xcb_key_symbols_free(symbols); + xcb_xvmc_query_version_cookie_t cookie = xcb_xvmc_query_version(connection); xcb_disconnect(connection); } -# endif +#endif + +#ifdef HAVE_X11_xcb_xv +# include <xcb/xcb.h> +# include <xcb/xv.h> + +static void test_xcb_xv(void) +{ + int screen_nbr; + xcb_connection_t* connection = xcb_connect(NULL, &screen_nbr); + xcb_xv_query_extension_cookie_t cookie = xcb_xv_query_extension(connection); + xcb_disconnect(connection); +} #endif @@ -537,28 +908,105 @@ int main(int argc, char* argv[]) #ifdef HAVE_X11_Xaw test_Xaw, #endif -#ifdef HAVE_xcb +#ifdef HAVE_X11_xcb test_xcb, #endif -#ifdef HAVE_xcb_cursor +#ifdef HAVE_X11_xcb_composite + test_xcb_composite, +#endif +#ifdef HAVE_X11_xcb_cursor test_xcb_cursor, #endif -#ifdef HAVE_xcb_randr +#ifdef HAVE_X11_xcb_damage + test_xcb_damage, +#endif +#ifdef HAVE_X11_xcb_dpms + test_xcb_dpms, +#endif +#ifdef HAVE_X11_xcb_dri2 + test_xcb_dri2, +#endif +#ifdef HAVE_X11_xcb_dri3 + test_xcb_dri3, +#endif +#ifdef HAVE_X11_xcb_errors + test_xcb_errors, +#endif +#ifdef HAVE_X11_xcb_ewmh + test_xcb_ewmh, +#endif +#ifdef HAVE_X11_xcb_glx + test_xcb_glx, +#endif +#ifdef HAVE_X11_xcb_icccm + test_xcb_icccm, +#endif +#ifdef HAVE_X11_xcb_image + test_xcb_image, +#endif +#ifdef HAVE_X11_xcb_keysyms + test_xcb_keysyms, +#endif +#ifdef HAVE_X11_xcb_present + test_xcb_present, +#endif +#ifdef HAVE_X11_xcb_randr test_xcb_randr, #endif -#ifdef HAVE_xcb_shape +#ifdef HAVE_X11_xcb_record + test_xcb_record, +#endif +#ifdef HAVE_X11_xcb_render + test_xcb_render, +#endif +#ifdef HAVE_X11_xcb_render_util + test_xcb_render_util, +#endif +#ifdef HAVE_X11_xcb_res + test_xcb_res, +#endif +#ifdef HAVE_X11_xcb_screensaver + test_xcb_screensaver, +#endif +#ifdef HAVE_X11_xcb_shape test_xcb_shape, #endif -#ifdef HAVE_xcb_util +#ifdef HAVE_X11_xcb_shm + test_xcb_shm, +#endif +#ifdef HAVE_X11_xcb_sync + test_xcb_sync, +#endif +#ifdef HAVE_X11_xcb_util test_xcb_util, #endif -#ifdef HAVE_xcb_xfixes +#ifdef HAVE_X11_xcb_xf86dri + test_xcb_xf86dri, +#endif +#ifdef HAVE_X11_xcb_xfixes test_xcb_xfixes, #endif -#ifdef HAVE_xcb_xrm +#ifdef HAVE_X11_xcb_xinerama + test_xcb_xinerama, +#endif +#ifdef HAVE_X11_xcb_xinput + test_xcb_xinput, +#endif +#ifdef HAVE_X11_xcb_xkb + test_xcb_xkb, +#endif +#ifdef HAVE_X11_xcb_xrm test_xcb_xrm, #endif - +#ifdef HAVE_X11_xcb_xtest + test_xcb_xtest, +#endif +#ifdef HAVE_X11_xcb_xvmc + test_xcb_xvmc, +#endif +#ifdef HAVE_X11_xcb_xv + test_xcb_xv, +#endif NULL, }; @@ -567,5 +1015,6 @@ int main(int argc, char* argv[]) // always 1 in the test harness which always returns the sentinel at the end // of the array. The array logic is there to ensure that the contents of // `fptrs` is not optimized out. +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" return (int)fptrs[(sizeof(fptrs) / sizeof(*fptrs)) - argc]; } diff --git a/Tests/QtAutogen/GlobalAutogenSystemUseInclude/CMakeLists.txt b/Tests/QtAutogen/GlobalAutogenSystemUseInclude/CMakeLists.txt new file mode 100644 index 0000000000..1095fb1e66 --- /dev/null +++ b/Tests/QtAutogen/GlobalAutogenSystemUseInclude/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.26) +project(GlobalAutogenSystemUseInclude) + +include("../AutogenCoreTest.cmake") + +block() + set(test_autogen_use_system_include ON) + set(CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE ${test_autogen_use_system_include}) + + add_executable(autogen_test_on main.cpp) + get_target_property(target_autogen_use_system_include autogen_test_on AUTOGEN_USE_SYSTEM_INCLUDE) + + if(NOT ${CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE} STREQUAL ${target_autogen_use_system_include}) + message(FATAL_ERROR "CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE not set") + endif() +endblock() + +block() + set(test_autogen_use_system_include OFF) + set(CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE ${test_autogen_use_system_include}) + + add_executable(autogen_test_off main.cpp) + get_target_property(target_autogen_use_system_include autogen_test_off AUTOGEN_USE_SYSTEM_INCLUDE) + + if(NOT ${CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE} STREQUAL ${target_autogen_use_system_include}) + message(FATAL_ERROR "CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE not set") + endif() +endblock() diff --git a/Tests/QtAutogen/GlobalAutogenSystemUseInclude/main.cpp b/Tests/QtAutogen/GlobalAutogenSystemUseInclude/main.cpp new file mode 100644 index 0000000000..f8b643afbf --- /dev/null +++ b/Tests/QtAutogen/GlobalAutogenSystemUseInclude/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/QtAutogen/RccAutogenBuildDir/CMakeLists.txt b/Tests/QtAutogen/RccAutogenBuildDir/CMakeLists.txt new file mode 100644 index 0000000000..9bdb68986d --- /dev/null +++ b/Tests/QtAutogen/RccAutogenBuildDir/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.16) +project(RccAutogenBuildDir) +include("../AutogenCoreTest.cmake") + +set(PROJECTS_ROOT ${CMAKE_BINARY_DIR}) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +macro(set_build_type_dependent varName debugValue releaseValue + relWithDebInfoValue minSizeRelValue) + + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(${varName} ${debugValue}) + elseif(CMAKE_BUILD_TYPE MATCHES Release) + set(${varName} ${releaseValue}) + elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + set(${varName} ${relWithDebInfoValue}) + elseif(CMAKE_BUILD_TYPE MATCHES MinSizeRel) + set(${varName} ${minSizeRelValue}) + endif() +endmacro() + +set_build_type_dependent(AUTOGEN_DIR agd agr ags agm) +add_library(testlib SHARED lib.h lib.cpp resource.qrc) +set_target_properties(testlib PROPERTIES AUTOGEN_BUILD_DIR "${PROJECTS_ROOT}/${AUTOGEN_DIR}/testlib_ag") +target_link_libraries(testlib ${QT_LIBRARIES}) + +set_build_type_dependent(AUTOGEN_DIR agd agr ags agm) +add_executable(autorcctest main.cpp lib.h) +set_target_properties(autorcctest PROPERTIES AUTOGEN_BUILD_DIR "${PROJECTS_ROOT}/${AUTOGEN_DIR}/autorcctest_ag") +target_link_libraries(autorcctest ${QT_LIBRARIES} testlib) diff --git a/Tests/QtAutogen/RccAutogenBuildDir/lib.cpp b/Tests/QtAutogen/RccAutogenBuildDir/lib.cpp new file mode 100644 index 0000000000..3a5c48208f --- /dev/null +++ b/Tests/QtAutogen/RccAutogenBuildDir/lib.cpp @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + void foo() +{ +} diff --git a/Tests/QtAutogen/RccAutogenBuildDir/lib.h b/Tests/QtAutogen/RccAutogenBuildDir/lib.h new file mode 100644 index 0000000000..28138f189a --- /dev/null +++ b/Tests/QtAutogen/RccAutogenBuildDir/lib.h @@ -0,0 +1,6 @@ +#ifndef LIB_H +#define LIB_H + +void foo(); + +#endif diff --git a/Tests/QtAutogen/RccAutogenBuildDir/main.cpp b/Tests/QtAutogen/RccAutogenBuildDir/main.cpp new file mode 100644 index 0000000000..a211f4011e --- /dev/null +++ b/Tests/QtAutogen/RccAutogenBuildDir/main.cpp @@ -0,0 +1,7 @@ +#include "lib.h" + +int main() +{ + foo(); + return 0; +} diff --git a/Tests/QtAutogen/RccAutogenBuildDir/resource.qrc b/Tests/QtAutogen/RccAutogenBuildDir/resource.qrc new file mode 100644 index 0000000000..90f4a8379a --- /dev/null +++ b/Tests/QtAutogen/RccAutogenBuildDir/resource.qrc @@ -0,0 +1,2 @@ +<!DOCTYPE RCC> +<RCC version="1.0"/> diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake index 412d511349..3e4f04d07e 100644 --- a/Tests/QtAutogen/Tests.cmake +++ b/Tests/QtAutogen/Tests.cmake @@ -1,8 +1,9 @@ -# Qt4 and Qt5 tests +# Qt4, Qt5 and Qt6 tests ADD_AUTOGEN_TEST(AutogenOriginDependsOff autogenOriginDependsOff) ADD_AUTOGEN_TEST(AutogenOriginDependsOn) ADD_AUTOGEN_TEST(AutogenTargetDepends) ADD_AUTOGEN_TEST(Complex QtAutogen) +ADD_AUTOGEN_TEST(GlobalAutogenSystemUseInclude) ADD_AUTOGEN_TEST(GlobalAutogenTarget) ADD_AUTOGEN_TEST(GlobalAutogenExecutable) ADD_AUTOGEN_TEST(LowMinimumVersion lowMinimumVersion) @@ -17,6 +18,7 @@ ADD_AUTOGEN_TEST(Parallel2 parallel2) ADD_AUTOGEN_TEST(Parallel3 parallel3) ADD_AUTOGEN_TEST(Parallel4 parallel4) ADD_AUTOGEN_TEST(ParallelAUTO parallelAUTO) +ADD_AUTOGEN_TEST(RccAutogenBuildDir) ADD_AUTOGEN_TEST(RccEmpty rccEmpty) ADD_AUTOGEN_TEST(RccOffMocLibrary) ADD_AUTOGEN_TEST(RccOnly rccOnly) @@ -46,7 +48,7 @@ if(QT_TEST_ALLOW_QT_MACROS) ADD_AUTOGEN_TEST(MocSkipSource) endif() -# Qt5 only tests +# Qt5 and Qt6 only tests if(QT_TEST_VERSION GREATER 4) ADD_AUTOGEN_TEST(MocMacroName mocMacroName) ADD_AUTOGEN_TEST(MocOsMacros) diff --git a/Tests/RunCMake/Autogen/AutogenUseSystemIncludeCommon.cmake b/Tests/RunCMake/Autogen/AutogenUseSystemIncludeCommon.cmake new file mode 100644 index 0000000000..bbefd5f55b --- /dev/null +++ b/Tests/RunCMake/Autogen/AutogenUseSystemIncludeCommon.cmake @@ -0,0 +1,10 @@ +enable_language(CXX) + +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui) + +set(CMAKE_AUTOMOC ON) + +add_library(dummy SHARED empty.cpp) +target_link_libraries(dummy Qt${with_qt_version}::Core + Qt${with_qt_version}::Widgets + Qt${with_qt_version}::Gui) diff --git a/Tests/RunCMake/Autogen/AutogenUseSystemIncludeOff.cmake b/Tests/RunCMake/Autogen/AutogenUseSystemIncludeOff.cmake new file mode 100644 index 0000000000..dfdbb98b5b --- /dev/null +++ b/Tests/RunCMake/Autogen/AutogenUseSystemIncludeOff.cmake @@ -0,0 +1,3 @@ +include("${CMAKE_CURRENT_LIST_DIR}/AutogenUseSystemIncludeCommon.cmake") + +set_target_properties(dummy PROPERTIES AUTOGEN_USE_SYSTEM_INCLUDE OFF) diff --git a/Tests/RunCMake/Autogen/AutogenUseSystemIncludeOn.cmake b/Tests/RunCMake/Autogen/AutogenUseSystemIncludeOn.cmake new file mode 100644 index 0000000000..f556ed43af --- /dev/null +++ b/Tests/RunCMake/Autogen/AutogenUseSystemIncludeOn.cmake @@ -0,0 +1,3 @@ +include("${CMAKE_CURRENT_LIST_DIR}/AutogenUseSystemIncludeCommon.cmake") + +set_target_properties(dummy PROPERTIES AUTOGEN_USE_SYSTEM_INCLUDE ON) diff --git a/Tests/RunCMake/Autogen/CMP0151-common.cmake b/Tests/RunCMake/Autogen/CMP0151-common.cmake new file mode 100644 index 0000000000..bbefd5f55b --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0151-common.cmake @@ -0,0 +1,10 @@ +enable_language(CXX) + +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui) + +set(CMAKE_AUTOMOC ON) + +add_library(dummy SHARED empty.cpp) +target_link_libraries(dummy Qt${with_qt_version}::Core + Qt${with_qt_version}::Widgets + Qt${with_qt_version}::Gui) diff --git a/Tests/RunCMake/Autogen/CMP0151-new.cmake b/Tests/RunCMake/Autogen/CMP0151-new.cmake new file mode 100644 index 0000000000..9c77e586f9 --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0151-new.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0151-common.cmake") diff --git a/Tests/RunCMake/Autogen/CMP0151-old.cmake b/Tests/RunCMake/Autogen/CMP0151-old.cmake new file mode 100644 index 0000000000..9c77e586f9 --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0151-old.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0151-common.cmake") diff --git a/Tests/RunCMake/Autogen/Inspect.cmake b/Tests/RunCMake/Autogen/Inspect.cmake new file mode 100644 index 0000000000..d5dc4b4093 --- /dev/null +++ b/Tests/RunCMake/Autogen/Inspect.cmake @@ -0,0 +1,13 @@ +enable_language(CXX) + +set(info "") +foreach(var + CMAKE_INCLUDE_FLAG_CXX + CMAKE_INCLUDE_SYSTEM_FLAG_CXX + ) + if(DEFINED ${var}) + string(APPEND info "set(${var} \"${${var}}\")\n") + endif() +endforeach() + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}") diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake index 6a3c49b534..45051326cb 100644 --- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake +++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake @@ -22,4 +22,70 @@ if (DEFINED with_qt_version) set(RunCMake_TEST_NO_CLEAN 1) run_cmake_command(MocPredefs-build ${CMAKE_COMMAND} --build . --config Debug) endblock() + + # Detect information from the toolchain: + # - CMAKE_INCLUDE_FLAG_CXX + # - CMAKE_INCLUDE_SYSTEM_FLAG_CXX + run_cmake(Inspect) + include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake") + + if(CMAKE_INCLUDE_SYSTEM_FLAG_CXX) + if(RunCMake_GENERATOR MATCHES "Visual Studio") + string(REGEX REPLACE "^-" "/" test_expect_stdout "${CMAKE_INCLUDE_SYSTEM_FLAG_CXX}") + else() + set(test_expect_stdout "-*${CMAKE_INCLUDE_SYSTEM_FLAG_CXX}") + endif() + string(APPEND test_expect_stdout " *(\"[^\"]*|([^ ]|\\ )*)[\\/]dummy_autogen[\\/]include") + if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + string(APPEND test_expect_stdout "_Debug") + endif() + + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0151-new-build) + run_cmake_with_options(CMP0151-new ${RunCMake_TEST_OPTIONS} -DCMAKE_POLICY_DEFAULT_CMP0151=NEW) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_EXPECT_stdout "${test_expect_stdout}") + message(STATUS "RunCMake_TEST_EXPECT_stdout: ${RunCMake_TEST_EXPECT_stdout}") + run_cmake_command(CMP0151-new-build ${CMAKE_COMMAND} --build . --config Debug --verbose) + endblock() + + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AutogenUseSystemIncludeOn-build) + run_cmake_with_options(AutogenUseSystemIncludeOn ${RunCMake_TEST_OPTIONS} -DCMAKE_POLICY_DEFAULT_CMP0151=NEW) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_EXPECT_stdout "${test_expect_stdout}") + message(STATUS "RunCMake_TEST_EXPECT_stdout: ${RunCMake_TEST_EXPECT_stdout}") + run_cmake_command(AutogenUseSystemIncludeOn ${CMAKE_COMMAND} --build . --config Debug --verbose) + endblock() + endif() + + if(CMAKE_INCLUDE_FLAG_CXX) + if(RunCMake_GENERATOR MATCHES "Visual Studio") + string(REGEX REPLACE "^-" "/" test_expect_stdout "${CMAKE_INCLUDE_FLAG_CXX}") + else() + set(test_expect_stdout "-*${CMAKE_INCLUDE_FLAG_CXX}") + endif() + string(APPEND test_expect_stdout " *(\"[^\"]*|([^ ]|\\ )*)[\\/]dummy_autogen[\\/]include") + if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + string(APPEND test_expect_stdout "_Debug") + endif() + + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0151-old-build) + run_cmake_with_options(CMP0151-old ${RunCMake_TEST_OPTIONS} -DCMAKE_POLICY_DEFAULT_CMP0151=OLD) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_EXPECT_stdout "${test_expect_stdout}") + message(STATUS "RunCMake_TEST_EXPECT_stdout: ${RunCMake_TEST_EXPECT_stdout}") + run_cmake_command(CMP0151-old-build ${CMAKE_COMMAND} --build . --config Debug --verbose) + endblock() + + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AutogenUseSystemIncludeOff-build) + run_cmake_with_options(AutogenUseSystemIncludeOff ${RunCMake_TEST_OPTIONS} -DCMAKE_POLICY_DEFAULT_CMP0151=NEW) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_EXPECT_stdout "${test_expect_stdout}") + message(STATUS "RunCMake_TEST_EXPECT_stdout: ${RunCMake_TEST_EXPECT_stdout}") + run_cmake_command(AutogenUseSystemIncludeOff ${CMAKE_COMMAND} --build . --config Debug --verbose) + endblock() + endif() endif () diff --git a/Tests/RunCMake/BuildDepends/LinkDepends.cmake b/Tests/RunCMake/BuildDepends/LinkDepends.cmake new file mode 100644 index 0000000000..a414e03597 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/LinkDepends.cmake @@ -0,0 +1,22 @@ + +enable_language(C) + +include("${CMAKE_BINARY_DIR}/../LinkDependsExternalLibrary-build/ExternalLibrary-debug.cmake") +cmake_path(GET EXTERNAL_LIBRARY PARENT_PATH EXTERNAL_DIR) + +add_library(LinkDependsLib SHARED "${CMAKE_CURRENT_BINARY_DIR}/lib_depends.c") +target_link_directories(LinkDependsLib PRIVATE "${EXTERNAL_DIR}") +target_link_libraries(LinkDependsLib PRIVATE External) + +add_executable(LinkDependsExe "${CMAKE_CURRENT_BINARY_DIR}/exe_depends.c") +target_link_directories(LinkDependsExe PRIVATE "${EXTERNAL_DIR}") +target_link_libraries(LinkDependsExe PRIVATE External) + + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake" + CONTENT " +set(check_pairs + \"$<TARGET_FILE:LinkDependsLib>|${EXTERNAL_LIBRARY}\" + \"$<TARGET_FILE:LinkDependsExe>|${EXTERNAL_LIBRARY}\" + ) +") diff --git a/Tests/RunCMake/BuildDepends/LinkDepends.step1.cmake b/Tests/RunCMake/BuildDepends/LinkDepends.step1.cmake new file mode 100644 index 0000000000..5ce55b0177 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/LinkDepends.step1.cmake @@ -0,0 +1,23 @@ + +file(WRITE "${RunCMake_TEST_BINARY_DIR}/lib_depends.c" [[ + +extern void external(void); + +void lib_depends(void) +{ + external(); +} +]]) + + +file(WRITE "${RunCMake_TEST_BINARY_DIR}/exe_depends.c" [[ + +extern void external(void); + +int main(void) +{ + external(); + + return 0; +} +]]) diff --git a/Tests/RunCMake/BuildDepends/LinkDepends.step2.cmake b/Tests/RunCMake/BuildDepends/LinkDepends.step2.cmake new file mode 100644 index 0000000000..f2c0067747 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/LinkDepends.step2.cmake @@ -0,0 +1,4 @@ + +include ("${RunCMake_TEST_BINARY_DIR}/../LinkDependsExternalLibrary-build/ExternalLibrary-debug.cmake") + +file(TOUCH "${EXTERNAL_LIBRARY}") diff --git a/Tests/RunCMake/BuildDepends/LinkDependsCheck.cmake b/Tests/RunCMake/BuildDepends/LinkDependsCheck.cmake new file mode 100644 index 0000000000..a21096b2ae --- /dev/null +++ b/Tests/RunCMake/BuildDepends/LinkDependsCheck.cmake @@ -0,0 +1,11 @@ + +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/LinkDependsUseLinker.cmake" + "set(CMAKE_C_LINK_DEPENDS_USE_LINKER \"${CMAKE_C_LINK_DEPENDS_USE_LINKER}\")\n") + + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake" + CONTENT " +# no required actions +") diff --git a/Tests/RunCMake/BuildDepends/LinkDependsExternalLibrary.cmake b/Tests/RunCMake/BuildDepends/LinkDependsExternalLibrary.cmake new file mode 100644 index 0000000000..fe6575c9b8 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/LinkDependsExternalLibrary.cmake @@ -0,0 +1,13 @@ + +enable_language(C) + +add_library(External SHARED "${CMAKE_CURRENT_BINARY_DIR}/external.c") + +file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/ExternalLibrary-$<LOWER_CASE:$<CONFIG>>.cmake" + CONTENT "set(EXTERNAL_LIBRARY \"$<TARGET_LINKER_FILE:External>\")\n") + + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake" + CONTENT " +# no required actions +") diff --git a/Tests/RunCMake/BuildDepends/LinkDependsExternalLibrary.step1.cmake b/Tests/RunCMake/BuildDepends/LinkDependsExternalLibrary.step1.cmake new file mode 100644 index 0000000000..df302f7614 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/LinkDependsExternalLibrary.step1.cmake @@ -0,0 +1,11 @@ + +file(WRITE "${RunCMake_TEST_BINARY_DIR}/external.c" [[ + + +#if defined(_WIN32) +__declspec(dllexport) +#endif + void external(void) +{ +} +]]) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 809907931d..b52758045e 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -194,3 +194,15 @@ if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 " OR endif() run_BuildDepends(CustomCommandUnityBuild) unset(run_BuildDepends_skip_step_2) + +#if (RunCMake_GENERATOR MATCHES "Make|Ninja" AND CMAKE_C_LINK_DEPENDS_USE_LINKER) +if (RunCMake_GENERATOR MATCHES "Make|Ninja") + set(run_BuildDepends_skip_step_2 1) + run_BuildDepends(LinkDependsCheck) + include("${RunCMake_BINARY_DIR}/LinkDependsCheck-build/LinkDependsUseLinker.cmake") + if (CMAKE_C_LINK_DEPENDS_USE_LINKER) + run_BuildDepends(LinkDependsExternalLibrary) + unset(run_BuildDepends_skip_step_2) + run_BuildDepends(LinkDepends) + endif() +endif() diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt index 5a035596e3..ac01c80b32 100644 --- a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt @@ -1,5 +1,5 @@ CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\): - list index: (-2147483643|2147483647) out of range \(-5, 4\) + list index: (-2147483648|2147483647) out of range \(-5, 4\) Call Stack \(most recent call first\): CMP0121-ERANGE-OLD.cmake:2 \(include\) CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt index cb4ea46439..c644dd3618 100644 --- a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt @@ -9,7 +9,7 @@ Call Stack \(most recent call first\): This warning is for project developers. Use -Wno-dev to suppress it. .* CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\): - list index: (-2147483643|2147483647) out of range \(-5, 4\) + list index: (-2147483648|2147483647) out of range \(-5, 4\) Call Stack \(most recent call first\): CMP0121-ERANGE-WARN.cmake:2 \(include\) CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/CMP0150/CMP0150-NEW-build-stdout.txt b/Tests/RunCMake/CMP0150/CMP0150-NEW-build-stdout.txt new file mode 100644 index 0000000000..9e71b731c7 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-NEW-build-stdout.txt @@ -0,0 +1,7 @@ +.*-- Configured bottom project +.*ExternalProject for ep-Y +.*-- Configured bottom project +[^\n]*-- Completed configuring project middle +.*-- Configured bottom project +.*ExternalProject for ep-X +.*Non-ep top project diff --git a/Tests/RunCMake/CMP0150/CMP0150-NEW-resolve.cmake b/Tests/RunCMake/CMP0150/CMP0150-NEW-resolve.cmake new file mode 100644 index 0000000000..f43f3d5f7b --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-NEW-resolve.cmake @@ -0,0 +1,107 @@ +include(ExternalProject/shared_internal_commands) + +function(test_resolve parentUrl relativeUrl expectedResult) + _ep_resolve_relative_git_remote(result "${parentUrl}" "${relativeUrl}") + if(NOT result STREQUAL expectedResult) + message(SEND_ERROR "URL resolved to unexpected result:\n" + " Expected: ${expectedResult}\n" + " Actual : ${result}" + ) + endif() +endfunction() + +test_resolve( + "https://example.com/group/parent" + "../other" + "https://example.com/group/other" +) +test_resolve( + "https://example.com/group/parent" + "../../alt/other" + "https://example.com/alt/other" +) + +test_resolve( + "git@example.com:group/parent" + "../other" + "git@example.com:group/other" +) +test_resolve( + "git@example.com:group/parent" + "../../alt/other" + "git@example.com:alt/other" +) +test_resolve( + "git@example.com:/group/parent" + "../other" + "git@example.com:/group/other" +) +test_resolve( + "git@example.com:/group/parent" + "../../alt/other" + "git@example.com:/alt/other" +) +test_resolve( + "git+ssh://git@example.com:group/parent" + "../other" + "git+ssh://git@example.com:group/other" +) +test_resolve( + "ssh://git@example.com:1234/group/parent" + "../../alt/other" + "ssh://git@example.com:1234/alt/other" +) + +test_resolve( + "file:///group/parent" + "../other" + "file:///group/other" +) +test_resolve( + "file:///group/parent" + "../../alt/other" + "file:///alt/other" +) +test_resolve( + "file:///~/group/parent" + "../../other" + "file:///~/other" +) +test_resolve( + "/group/parent" + "../other" + "/group/other" +) +test_resolve( + "/group/parent" + "../../alt/other" + "/alt/other" +) +test_resolve( + "C:/group/parent" + "../other" + "C:/group/other" +) +test_resolve( + "C:/group/parent" + "../../alt/other" + "C:/alt/other" +) + +test_resolve( + "x-Test+v1.0://example.com/group/parent" + "../other" + "x-Test+v1.0://example.com/group/other" +) + +# IPv6 literals +test_resolve( + "http://[::1]/group/parent" + "../../alt/other" + "http://[::1]/alt/other" +) +test_resolve( + "git@[::1]:group/parent" + "../../alt/other" + "git@[::1]:alt/other" +) diff --git a/Tests/RunCMake/CMP0150/CMP0150-NEW-stdout.txt b/Tests/RunCMake/CMP0150/CMP0150-NEW-stdout.txt new file mode 100644 index 0000000000..0f25fabf40 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-NEW-stdout.txt @@ -0,0 +1,4 @@ +-- Configured bottom project +-- Completed configuring project middle +-- Completed configuring project top +-- Configuring done diff --git a/Tests/RunCMake/CMP0150/CMP0150-NEW.cmake b/Tests/RunCMake/CMP0150/CMP0150-NEW.cmake new file mode 100644 index 0000000000..c1c5607af7 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-NEW.cmake @@ -0,0 +1,45 @@ +set(policyCommand "cmake_policy(SET CMP0150 NEW)") + +# Need to keep paths and file names short to avoid hitting limits on Windows. +# Directory names "a" through to "g" are used here according to the following: +# a = Top project +# b/c = Middle project +# d = Bottom project +# e/f = Cloned Top project +# g = Build directory for cloned Top project +# +# Dependency names map as follows: +# X = middle dependency +# Y = bottom dependency + +set(projName top) +set(depName X) +set(epRelativeGitRepo ../b/c) +set(fcRelativeGitRepo ../b/c) +configure_file(CMakeLists.txt.in a/CMakeLists.txt @ONLY) +initGitRepo("${CMAKE_CURRENT_BINARY_DIR}/a") + +set(projName middle) +set(depName Y) +set(epRelativeGitRepo ../../d) +set(fcRelativeGitRepo ../../d) +configure_file(CMakeLists.txt.in b/c/CMakeLists.txt @ONLY) +initGitRepo("${CMAKE_CURRENT_BINARY_DIR}/b/c") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/d") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/d/CMakeLists.txt" [[ +cmake_minimum_required(VERSION 3.26) +project(bottom LANGUAGES NONE) +message(STATUS "Configured bottom project") +]]) +initGitRepo("${CMAKE_CURRENT_BINARY_DIR}/d") + +set(clonedTopDir "${CMAKE_CURRENT_BINARY_DIR}/e/f") +file(MAKE_DIRECTORY "${clonedTopDir}") +execGitCommand(${CMAKE_CURRENT_BINARY_DIR} clone --quiet "file://${CMAKE_CURRENT_BINARY_DIR}/a" "${clonedTopDir}") +add_subdirectory("${clonedTopDir}" "${CMAKE_CURRENT_BINARY_DIR}/g") + +# Ensure build order is predictable +add_custom_target(non-ep-top ALL COMMAND ${CMAKE_COMMAND} -E echo "Non-ep top project") +add_dependencies(non-ep-top ep-X) +add_dependencies(ep-X ep-Y) diff --git a/Tests/RunCMake/CMP0150/CMP0150-OLD-build-stdout.txt b/Tests/RunCMake/CMP0150/CMP0150-OLD-build-stdout.txt new file mode 100644 index 0000000000..0150af769b --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-OLD-build-stdout.txt @@ -0,0 +1,3 @@ +.*-- Configured bottom project +.*ExternalProject for ep-bottom +.*Non-ep top project diff --git a/Tests/RunCMake/CMP0150/CMP0150-OLD-common.cmake b/Tests/RunCMake/CMP0150/CMP0150-OLD-common.cmake new file mode 100644 index 0000000000..69748f7325 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-OLD-common.cmake @@ -0,0 +1,21 @@ +# There's no point testing more than one level for OLD, since the behavior only +# depends on the current build, not anything about the parent git repo, etc. +set(projName top) +set(depName bottom) +set(epRelativeGitRepo ../../../Bottom) +set(fcRelativeGitRepo ../Bottom) +configure_file(CMakeLists.txt.in Top/CMakeLists.txt @ONLY) + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Bottom") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/Bottom/CMakeLists.txt" [[ +cmake_minimum_required(VERSION 3.26) +project(bottom LANGUAGES NONE) +message(STATUS "Configured bottom project") +]]) +initGitRepo("${CMAKE_CURRENT_BINARY_DIR}/Bottom") + +add_subdirectory("${CMAKE_CURRENT_BINARY_DIR}/Top" "${CMAKE_CURRENT_BINARY_DIR}/Top-build") + +# Ensure build order is predictable +add_custom_target(non-ep-top ALL COMMAND ${CMAKE_COMMAND} -E echo "Non-ep top project") +add_dependencies(non-ep-top ep-bottom) diff --git a/Tests/RunCMake/CMP0150/CMP0150-OLD-stdout.txt b/Tests/RunCMake/CMP0150/CMP0150-OLD-stdout.txt new file mode 100644 index 0000000000..680f9c1d3d --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-OLD-stdout.txt @@ -0,0 +1,3 @@ +-- Configured bottom project +-- Completed configuring project top +-- Configuring done diff --git a/Tests/RunCMake/CMP0150/CMP0150-OLD.cmake b/Tests/RunCMake/CMP0150/CMP0150-OLD.cmake new file mode 100644 index 0000000000..6b58e70c83 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-OLD.cmake @@ -0,0 +1,2 @@ +set(policyCommand "cmake_policy(SET CMP0150 OLD)") +include(CMP0150-OLD-common.cmake) diff --git a/Tests/RunCMake/CMP0150/CMP0150-WARN-build-stdout.txt b/Tests/RunCMake/CMP0150/CMP0150-WARN-build-stdout.txt new file mode 100644 index 0000000000..0150af769b --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-WARN-build-stdout.txt @@ -0,0 +1,3 @@ +.*-- Configured bottom project +.*ExternalProject for ep-bottom +.*Non-ep top project diff --git a/Tests/RunCMake/CMP0150/CMP0150-WARN-stderr.txt b/Tests/RunCMake/CMP0150/CMP0150-WARN-stderr.txt new file mode 100644 index 0000000000..74c932aaa2 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-WARN-stderr.txt @@ -0,0 +1,25 @@ +CMake Warning \(dev\) at .*/Modules/ExternalProject/shared_internal_commands\.cmake:[0-9]+ \(message\): + Policy CMP0150 is not set: ExternalProject_Add and FetchContent_Declare + commands treat relative GIT_REPOSITORY paths as being relative to the + parent project's remote\. Run "cmake --help-policy CMP0150" for policy + details\. Use the cmake_policy command to set the policy and suppress this + warning\. + + A relative GIT_REPOSITORY path was detected\. This will be interpreted as a + local path to where the project is being cloned\. Set GIT_REPOSITORY to an + absolute path or set policy CMP0150 to NEW to avoid this warning\. +Call Stack \(most recent call first\): + .*/Modules/ExternalProject\.cmake:[0-9]+ \(_ep_resolve_git_remote\) +.* +CMake Warning \(dev\) at .*/Modules/ExternalProject/shared_internal_commands\.cmake:[0-9]+ \(message\): + Policy CMP0150 is not set: ExternalProject_Add and FetchContent_Declare + commands treat relative GIT_REPOSITORY paths as being relative to the + parent project's remote\. Run "cmake --help-policy CMP0150" for policy + details\. Use the cmake_policy command to set the policy and suppress this + warning\. + + A relative GIT_REPOSITORY path was detected\. This will be interpreted as a + local path to where the project is being cloned\. Set GIT_REPOSITORY to an + absolute path or set policy CMP0150 to NEW to avoid this warning\. +Call Stack \(most recent call first\): + .*/Modules/FetchContent\.cmake:[0-9]+ \(_ep_resolve_git_remote\) diff --git a/Tests/RunCMake/CMP0150/CMP0150-WARN-stdout.txt b/Tests/RunCMake/CMP0150/CMP0150-WARN-stdout.txt new file mode 100644 index 0000000000..680f9c1d3d --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-WARN-stdout.txt @@ -0,0 +1,3 @@ +-- Configured bottom project +-- Completed configuring project top +-- Configuring done diff --git a/Tests/RunCMake/CMP0150/CMP0150-WARN.cmake b/Tests/RunCMake/CMP0150/CMP0150-WARN.cmake new file mode 100644 index 0000000000..20fd45d4e6 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMP0150-WARN.cmake @@ -0,0 +1,2 @@ +set(policyCommand "") +include(CMP0150-OLD-common.cmake) diff --git a/Tests/RunCMake/CMP0150/CMakeLists.txt b/Tests/RunCMake/CMP0150/CMakeLists.txt new file mode 100644 index 0000000000..371dccc7b2 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.25) +project(${RunCMake_TEST} NONE) + +find_package(Git REQUIRED) + +function(execGitCommand workDir) + execute_process( + WORKING_DIRECTORY "${workDir}" + COMMAND "${GIT_EXECUTABLE}" ${ARGN} + COMMAND_ECHO STDOUT + COMMAND_ERROR_IS_FATAL ANY + ) +endfunction() + +function(initGitRepo workDir) + # init.defaultBranch only works with git 2.28 or later, so we must use the + # historical default branch name "master". Force the old default in case test + # sites have overridden the default to something else. + execGitCommand("${workDir}" -c init.defaultBranch=master init) + execGitCommand("${workDir}" config user.email "testauthor@cmake.org") + execGitCommand("${workDir}" config user.name testauthor) + execGitCommand("${workDir}" config core.autocrlf false) + execGitCommand("${workDir}" add CMakeLists.txt) + execGitCommand("${workDir}" commit -m "Initial commit") +endfunction() + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0150/CMakeLists.txt.in b/Tests/RunCMake/CMP0150/CMakeLists.txt.in new file mode 100644 index 0000000000..db6cfc76e0 --- /dev/null +++ b/Tests/RunCMake/CMP0150/CMakeLists.txt.in @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.25) +project(@projName@ LANGUAGES NONE) + +@policyCommand@ + +include(ExternalProject) +ExternalProject_Add(ep-@depName@ + GIT_REPOSITORY @epRelativeGitRepo@ + GIT_TAG master + GIT_CONFIG init.defaultBranch=master + TEST_COMMAND "" + INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "ExternalProject for ep-@depName@" +) + +include(FetchContent) +FetchContent_Declare(@depName@ + GIT_REPOSITORY @fcRelativeGitRepo@ + GIT_TAG master + GIT_CONFIG init.defaultBranch=master +) +FetchContent_MakeAvailable(@depName@) + +message(STATUS "Completed configuring project @projName@") diff --git a/Tests/RunCMake/CMP0150/RunCMakeTest.cmake b/Tests/RunCMake/CMP0150/RunCMakeTest.cmake new file mode 100644 index 0000000000..940c33e65b --- /dev/null +++ b/Tests/RunCMake/CMP0150/RunCMakeTest.cmake @@ -0,0 +1,17 @@ +include(RunCMake) + +function(test_CMP0150 val) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${val}-build) + run_cmake(CMP0150-${val}) + set(RunCMake_TEST_NO_CLEAN TRUE) + # Some git versions write clone messages to stderr. These would cause the + # test to fail, so we need to merge them into stdout. + set(RunCMake_TEST_OUTPUT_MERGE TRUE) + run_cmake_command(CMP0150-${val}-build ${CMAKE_COMMAND} --build .) +endfunction() + +test_CMP0150(WARN) +test_CMP0150(OLD) +test_CMP0150(NEW) + +run_cmake_script(CMP0150-NEW-resolve) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index f05f784d7d..ada913299b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -160,6 +160,7 @@ endif() add_RunCMake_test(CMP0132) add_RunCMake_test(CMP0135) add_RunCMake_test(CMP0139) +add_RunCMake_test(CMP0150) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode @@ -294,6 +295,7 @@ endif() add_RunCMake_test(BuildDepends -DMSVC_VERSION=${MSVC_VERSION} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} + -DCMAKE_C_LINK_DEPENDS_USE_COMPILER=${CMAKE_C_LINK_DEPENDS_USE_COMPILER} -DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS} ) if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") @@ -370,6 +372,7 @@ add_RunCMake_test(GenEx-TARGET_PROPERTY) add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS) add_RunCMake_test(GenEx-PATH) add_RunCMake_test(GenEx-PATH_EQUAL) +add_RunCMake_test(GenEx-LIST) add_RunCMake_test(GeneratorExpression) add_RunCMake_test(GeneratorInstance) add_RunCMake_test(GeneratorPlatform) diff --git a/Tests/RunCMake/CMakePresets/EmptyPenvInInclude-result.txt b/Tests/RunCMake/CMakePresets/EmptyPenvInInclude-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CMakePresets/EmptyPenvInInclude-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/EmptyPenvInInclude-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPenvInInclude-stderr.txt new file mode 100644 index 0000000000..e0f858a1e1 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/EmptyPenvInInclude-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/EmptyPenvInInclude: +Error: @3,15: Invalid "include" field + "include": \["\$penv\{\}"\], + \^$ diff --git a/Tests/RunCMake/CMakePresets/EmptyPenvInInclude.json.in b/Tests/RunCMake/CMakePresets/EmptyPenvInInclude.json.in new file mode 100644 index 0000000000..651b0de1b9 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/EmptyPenvInInclude.json.in @@ -0,0 +1,11 @@ +{ + "version": 7, + "include": ["$penv{}"], + "configurePresets": [ + { + "name": "EmptyPenvInInclude", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt b/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt new file mode 100644 index 0000000000..d3f1afceb2 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt @@ -0,0 +1,5 @@ +^Not searching for unused variables given on the command line\. +Available configure presets: + + "Include" + "IncludeCommon"$ diff --git a/Tests/RunCMake/CMakePresets/IncludeExpansion.json.in b/Tests/RunCMake/CMakePresets/IncludeExpansion.json.in new file mode 100644 index 0000000000..b4f82927b5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/IncludeExpansion.json.in @@ -0,0 +1,10 @@ +{ + "version": 7, + "include": ["$penv{TEST_ENV_INCLUDE_DIR}/IncludeCommon.json"], + "configurePresets": [ + { + "name": "Include", + "inherits": ["IncludeCommon"] + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index d67e8b14ee..c4a8b3f080 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -146,6 +146,7 @@ run_cmake_presets(NoSuchMacro) run_cmake_presets(EnvCycle) run_cmake_presets(EmptyEnv) run_cmake_presets(EmptyPenv) +run_cmake_presets(EmptyPenvInInclude) run_cmake_presets(InvalidRegex) set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) run_cmake_presets(ConditionFuture) @@ -393,6 +394,12 @@ set(CMakePresets_EXTRA_FILES "${RunCMake_SOURCE_DIR}/subdir/CMakePresets.json.in" ) run_cmake_presets(Include --list-presets) +set(CMakePresets_EXTRA_FILES + "${RunCMake_SOURCE_DIR}/IncludeCommon.json.in" + ) +set(ENV{TEST_ENV_INCLUDE_DIR} ${RunCMake_BINARY_DIR}/IncludeExpansion) +run_cmake_presets(IncludeExpansion --list-presets) +unset(ENV{TEST_ENV_INCLUDE_DIR}) unset(CMakePresets_EXTRA_FILES) run_cmake_presets(IncludeNotFound) run_cmake_presets(IncludeCycle) diff --git a/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx b/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx index 65f17b6e32..2824fbfe31 100644 --- a/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx +++ b/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx @@ -19,6 +19,7 @@ #include "cmCTestTestHandler.h" #include "cmFileLock.h" #include "cmFileLockResult.h" +#include "cmList.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -282,7 +283,7 @@ static int doVerify(int argc, char const* const* argv) if (argc == 5) { testNames = argv[4]; } - auto testNameList = cmExpandedList(testNames, false); + cmList testNameList{ testNames }; std::set<std::string> testNameSet(testNameList.begin(), testNameList.end()); cmCTestResourceSpec spec; diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index fda18b5c08..eb52975265 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -848,8 +848,204 @@ def gen_check_targets(c, g, inSource): for e in expected: if e["type"] == "UTILITY": if e["id"] == "^ZERO_CHECK::@6890427a1f51a3e7e1df$": + # The json files have data for Xcode. Substitute data for VS. e["sources"] = [ { + "path": "^CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^alias/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^codemodel-v2\\.cmake$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^custom/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^cxx/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^dir/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^dir/dir/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^fileset/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^imported/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^include_test\\.cmake$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^interface/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^object/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { + "path": "^subdir/CMakeLists\\.txt$", + "isGenerated": None, + "fileSetName": None, + "sourceGroupName": "", + "compileGroupLanguage": None, + "backtrace": [ + { + "file": "^CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + { "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/([0-9a-f]+/)?generate\\.stamp\\.rule$", "isGenerated": True, "fileSetName": None, @@ -867,6 +1063,24 @@ def gen_check_targets(c, g, inSource): ] e["sourceGroups"] = [ { + "name": "", + "sourcePaths": [ + "^CMakeLists\\.txt$", + "^alias/CMakeLists\\.txt$", + "^codemodel-v2\\.cmake$", + "^custom/CMakeLists\\.txt$", + "^cxx/CMakeLists\\.txt$", + "^dir/CMakeLists\\.txt$", + "^dir/dir/CMakeLists\\.txt$", + "^fileset/CMakeLists\\.txt$", + "^imported/CMakeLists\\.txt$", + "^include_test\\.cmake$", + "^interface/CMakeLists\\.txt$", + "^object/CMakeLists\\.txt$", + "^subdir/CMakeLists\\.txt$", + ], + }, + { "name": "CMake Rules", "sourcePaths": [ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/([0-9a-f]+/)?generate\\.stamp\\.rule$", diff --git a/Tests/RunCMake/GenEx-LIST/APPEND.cmake.in b/Tests/RunCMake/GenEx-LIST/APPEND.cmake.in new file mode 100644 index 0000000000..19e1d127bb --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/APPEND.cmake.in @@ -0,0 +1,34 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(APPEND listvar e) +set (output "$<LIST:APPEND,a;b;c;d,e>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(APPEND listvar e f) +set (output "$<LIST:APPEND,a;b;c;d,e,f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(APPEND listvar e f) +set (output "$<LIST:APPEND,a;b;c;d,e;f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +unset(listvar) +list(APPEND listvar e f) +set (output "$<LIST:APPEND,,e,f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:APPEND..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/CMakeLists.txt b/Tests/RunCMake/GenEx-LIST/CMakeLists.txt new file mode 100644 index 0000000000..5161b995a9 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.18...3.25) + +project(${RunCMake_TEST} NONE) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator-result.txt b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator-stderr.txt b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator-stderr.txt new file mode 100644 index 0000000000..3064c00ee5 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at FILTER-wrong-operator.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:FILTER,a;b;c,WRONG_OPERATOR,\^a> + + sub-command FILTER does not recognize operator "WRONG_OPERATOR". It must + be either INCLUDE or EXCLUDE. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator.cmake b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator.cmake new file mode 100644 index 0000000000..e01b4fe7ae --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-operator.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:FILTER,a;b;c,WRONG_OPERATOR,^a>") diff --git a/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex-result.txt b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex-stderr.txt b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex-stderr.txt new file mode 100644 index 0000000000..b2f9b8a97b --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at FILTER-wrong-regex.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:FILTER,a;b;c,INCLUDE,\^\(a> + + sub-command FILTER, failed to compile regex "\^\(a". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex.cmake b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex.cmake new file mode 100644 index 0000000000..1311f319cd --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FILTER-wrong-regex.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:FILTER,a;b;c,INCLUDE,^(a>") diff --git a/Tests/RunCMake/GenEx-LIST/FIND.cmake.in b/Tests/RunCMake/GenEx-LIST/FIND.cmake.in new file mode 100644 index 0000000000..e2242c3a4c --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/FIND.cmake.in @@ -0,0 +1,20 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(FIND listvar "c" reference) +set (output "$<LIST:FIND,a;b;c;d,c>") +if (NOT output EQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(FIND listvar "e" reference) +set (output "$<LIST:FIND,a;b;c;d,e>") +if (NOT output EQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:FIND..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index1-result.txt b/Tests/RunCMake/GenEx-LIST/GET-wrong-index1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index1-stderr.txt b/Tests/RunCMake/GenEx-LIST/GET-wrong-index1-stderr.txt new file mode 100644 index 0000000000..dcd1f2f3bf --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index1-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at GET-wrong-index1.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:GET,,0> + + given empty list +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index1.cmake b/Tests/RunCMake/GenEx-LIST/GET-wrong-index1.cmake new file mode 100644 index 0000000000..4c395b318c --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index1.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:GET,,0>") diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index2-result.txt b/Tests/RunCMake/GenEx-LIST/GET-wrong-index2-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index2-stderr.txt b/Tests/RunCMake/GenEx-LIST/GET-wrong-index2-stderr.txt new file mode 100644 index 0000000000..20f1af4fd6 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index2-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at GET-wrong-index2.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:GET,a;b,2> + + index: 2 out of range \(-2, 1\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index2.cmake b/Tests/RunCMake/GenEx-LIST/GET-wrong-index2.cmake new file mode 100644 index 0000000000..28c97e2fd8 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index2.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:GET,a;b,2>") diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index3-result.txt b/Tests/RunCMake/GenEx-LIST/GET-wrong-index3-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index3-stderr.txt b/Tests/RunCMake/GenEx-LIST/GET-wrong-index3-stderr.txt new file mode 100644 index 0000000000..a5dccbe953 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index3-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at GET-wrong-index3.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:GET,a;b,1,-3> + + index: -3 out of range \(-2, 1\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/GET-wrong-index3.cmake b/Tests/RunCMake/GenEx-LIST/GET-wrong-index3.cmake new file mode 100644 index 0000000000..fd7be176d3 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET-wrong-index3.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:GET,a;b,1,-3>") diff --git a/Tests/RunCMake/GenEx-LIST/GET.cmake.in b/Tests/RunCMake/GenEx-LIST/GET.cmake.in new file mode 100644 index 0000000000..102eb42e3d --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/GET.cmake.in @@ -0,0 +1,20 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(GET listvar 0 2 reference) +set (output "$<LIST:GET,a;b;c;d,0,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(GET listvar 0 -3 2 reference) +set (output "$<LIST:GET,a;b;c;d,0,-3,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:GET..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1-result.txt b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1-stderr.txt b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1-stderr.txt new file mode 100644 index 0000000000..ce36fb1197 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at INSERT-wrong-index1.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:INSERT,a;b;c,4,d> + + index: 4 out of range \(-3, 3\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1.cmake b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1.cmake new file mode 100644 index 0000000000..ead5832418 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index1.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:INSERT,a;b;c,4,d>") diff --git a/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2-result.txt b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2-stderr.txt b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2-stderr.txt new file mode 100644 index 0000000000..f0ea1d70c3 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at INSERT-wrong-index2.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:INSERT,a;b;c,-4,d> + + index: -4 out of range \(-3, 3\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2.cmake b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2.cmake new file mode 100644 index 0000000000..c057b876a9 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT-wrong-index2.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:INSERT,a;b;c,-4,d>") diff --git a/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in b/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in new file mode 100644 index 0000000000..d3bb9b9b18 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(INSERT listvar 1 e) +set (output "$<LIST:INSERT,a;b;c;d,1,e>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) + +list(INSERT listvar 2 e f) +set (output "$<LIST:INSERT,a;b;c;d,2,e,f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(INSERT listvar 0 e f) +set (output "$<LIST:INSERT,a;b;c;d,0,e;f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(INSERT listvar -2 e f) +set (output "$<LIST:INSERT,a;b;c;d,-2,e;f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(INSERT listvar 3 e f) +set (output "$<LIST:INSERT,a;b;c;d,3,e;f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +unset(listvar) +list(INSERT listvar 0 e f) +set (output "$<LIST:INSERT,,0,e,f>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:INSERT..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/JOIN.cmake.in b/Tests/RunCMake/GenEx-LIST/JOIN.cmake.in new file mode 100644 index 0000000000..0a564507be --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/JOIN.cmake.in @@ -0,0 +1,35 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(JOIN listvar ":" reference) +set (output "$<LIST:JOIN,a;b;c;d,:>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(JOIN listvar "" reference) +set (output "$<LIST:JOIN,a;b;c;d,>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a) + +list(JOIN listvar ":" reference) +set (output "$<LIST:JOIN,a,:>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +unset(listvar) + +list(JOIN listvar ":" reference) +set (output "$<LIST:JOIN,,:>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +check_errors("LIST:JOIN..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/LENGTH.cmake.in b/Tests/RunCMake/GenEx-LIST/LENGTH.cmake.in new file mode 100644 index 0000000000..0840e11116 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/LENGTH.cmake.in @@ -0,0 +1,30 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(LENGTH listvar reference) +set (output "$<LIST:LENGTH,a;b;c;d>") +if (NOT output EQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar "") + +list(LENGTH listvar reference) +set (output "$<LIST:LENGTH,>") +if (NOT output EQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +unset(listvar) + +list(LENGTH listvar reference) +set (output "$<LIST:LENGTH,>") +if (NOT output EQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:LENGTH..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/POP_BACK.cmake.in b/Tests/RunCMake/GenEx-LIST/POP_BACK.cmake.in new file mode 100644 index 0000000000..ba95c839c0 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/POP_BACK.cmake.in @@ -0,0 +1,18 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(POP_BACK listvar) +set (output "$<LIST:POP_BACK,a;b;c;d>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set (output "$<LIST:POP_BACK,>") +if (NOT output STREQUAL "") + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:POP_BACK..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/POP_FRONT.cmake.in b/Tests/RunCMake/GenEx-LIST/POP_FRONT.cmake.in new file mode 100644 index 0000000000..0d676af60e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/POP_FRONT.cmake.in @@ -0,0 +1,18 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(POP_FRONT listvar) +set (output "$<LIST:POP_FRONT,a;b;c;d>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set (output "$<LIST:POP_FRONT,>") +if (NOT output STREQUAL "") + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:POP_FRONT..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/PREPEND.cmake.in b/Tests/RunCMake/GenEx-LIST/PREPEND.cmake.in new file mode 100644 index 0000000000..49b8f98239 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/PREPEND.cmake.in @@ -0,0 +1,34 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(PREPEND listvar e) +set (output "$<LIST:PREPEND,a;b;c;d,e>") +if (NOT output STREQUAL listvar) + list (PREPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(PREPEND listvar e f) +set (output "$<LIST:PREPEND,a;b;c;d,e,f>") +if (NOT output STREQUAL listvar) + list (PREPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(PREPEND listvar e f) +set (output "$<LIST:PREPEND,a;b;c;d,e;f>") +if (NOT output STREQUAL listvar) + list (PREPEND errors "returns bad value: ${output}") +endif() + +unset(listvar) +list(PREPEND listvar e f) +set (output "$<LIST:PREPEND,,e,f>") +if (NOT output STREQUAL listvar) + list (PREPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:PREPEND..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1-result.txt b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1-stderr.txt b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1-stderr.txt new file mode 100644 index 0000000000..b874f1d09b --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at REMOVE_AT-wrong-index1.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:REMOVE_AT,,0> + + index: 0 out of range \(0, 0\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1.cmake b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1.cmake new file mode 100644 index 0000000000..d87559e83b --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index1.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:REMOVE_AT,,0>") diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2-result.txt b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2-stderr.txt b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2-stderr.txt new file mode 100644 index 0000000000..509eed4b16 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at REMOVE_AT-wrong-index2.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:REMOVE_AT,a;b;c,3> + + index: 3 out of range \(-3, 2\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2.cmake b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2.cmake new file mode 100644 index 0000000000..7ecfad2281 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index2.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:REMOVE_AT,a;b;c,3>") diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3-result.txt b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3-stderr.txt b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3-stderr.txt new file mode 100644 index 0000000000..c8fc465062 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at REMOVE_AT-wrong-index3.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:REMOVE_AT,a;b;c,-4> + + index: -4 out of range \(-3, 2\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3.cmake b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3.cmake new file mode 100644 index 0000000000..f8f9a3e24b --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT-wrong-index3.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:REMOVE_AT,a;b;c,-4>") diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_AT.cmake.in b/Tests/RunCMake/GenEx-LIST/REMOVE_AT.cmake.in new file mode 100644 index 0000000000..42a94766f9 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_AT.cmake.in @@ -0,0 +1,25 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(REMOVE_AT listvar 1 3) +set (output "$<LIST:REMOVE_AT,a;b;c;d,1,3>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(REMOVE_AT listvar 1 -2) +set (output "$<LIST:REMOVE_AT,a;b;c;d,1;-2>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set (output "$<LIST:REMOVE_AT,a;b;c;d,1,0,3;2>") +if (NOT output STREQUAL "") + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:REMOVE_AT..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_DUPLICATES.cmake.in b/Tests/RunCMake/GenEx-LIST/REMOVE_DUPLICATES.cmake.in new file mode 100644 index 0000000000..8785ae522a --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_DUPLICATES.cmake.in @@ -0,0 +1,20 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(REMOVE_DUPLICATES listvar) +set (output "$<LIST:REMOVE_DUPLICATES,a;b;c;d>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar "b;c;b;a;a;c;b;a;c;b") +list(REMOVE_DUPLICATES listvar) +set (output "$<LIST:REMOVE_DUPLICATES,b;c;b;a;a;c;b;a;c;b>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:REMOVE_DUPLICATES..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/REMOVE_ITEM.cmake.in b/Tests/RunCMake/GenEx-LIST/REMOVE_ITEM.cmake.in new file mode 100644 index 0000000000..5434a5d51d --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REMOVE_ITEM.cmake.in @@ -0,0 +1,32 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) +list(REMOVE_ITEM listvar b d) +set (output "$<LIST:REMOVE_ITEM,a;b;c;d,b,d>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(REMOVE_ITEM listvar b e) +set (output "$<LIST:REMOVE_ITEM,a;b;c;d,b,e>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar a b c d) +list(REMOVE_ITEM listvar b a d c) +set (output "$<LIST:REMOVE_ITEM,a;b;c;d,b;a;d;c>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set (output "$<LIST:REMOVE_ITEM,,b;a;d;c>") +if (NOT output STREQUAL "") + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:REMOVE_ITEM..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/REVERSE.cmake.in b/Tests/RunCMake/GenEx-LIST/REVERSE.cmake.in new file mode 100644 index 0000000000..295e1a3c8a --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/REVERSE.cmake.in @@ -0,0 +1,19 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(REVERSE listvar) +set (output "$<LIST:REVERSE,a;b;c;d>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set (output "$<LIST:REVERSE,>") +if (NOT output STREQUAL "") + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:REVERSE..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LIST/RunCMakeTest.cmake new file mode 100644 index 0000000000..1946e84915 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/RunCMakeTest.cmake @@ -0,0 +1,130 @@ + +include(RunCMake) + +run_cmake(no-arguments) +run_cmake(bad-option) + +function(check_list_syntax name test) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-${test}-build) + set(RunCMake_TEST_VARIANT_DESCRIPTION " - ${name}") + run_cmake_with_options(${test} ${ARGN}) +endfunction() + +## Unexpected arguments +### sub-commands with one argument +foreach (subcommand IN ITEMS LENGTH POP_BACK POP_FRONT REMOVE_DUPLICATES REVERSE) + check_list_syntax (${subcommand} unexpected-arg "-DLIST_ARGUMENTS=${subcommand},ARG1,ARG2") +endforeach() + +### sub-commands with two arguments +foreach (subcommand IN ITEMS FIND JOIN) + check_list_syntax (${subcommand} unexpected-arg "-DLIST_ARGUMENTS=${subcommand},ARG1,ARG2,ARG3") +endforeach() + +### sub-commands with three arguments +foreach (subcommand IN ITEMS SUBLIST FILTER) + check_list_syntax (${subcommand} unexpected-arg "-DLIST_ARGUMENTS=${subcommand},ARG1,ARG2,ARG3,ARG4") +endforeach() + +# TRANSFORM sub-commands + set(RunCMake-stderr-file "TRANSFORM-unexpected-arg-stderr.txt") +foreach (action IN ITEMS TOLOWER TOUPPER STRIP) + check_list_syntax (TRANSFORM-${action} unexpected-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,${action},ARG2") +endforeach() +foreach (action IN ITEMS APPEND PREPEND) + check_list_syntax (TRANSFORM-${action} unexpected-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,${action},ARG2,ARG3") +endforeach() +foreach (action IN ITEMS REPLACE) + check_list_syntax (TRANSFORM-${action} unexpected-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,${action},ARG2,ARG3,ARG4") +endforeach() +check_list_syntax (TRANSFORM-SELECTOR-REGEX unexpected-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,STRIP,REGEX,ARG2,ARG3") +check_list_syntax (TRANSFORM-SELECTOR-FOR unexpected-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,STRIP,FOR,1,2,3,4") +unset(RunCMake-stderr-file) + +## Missing arguments +### sub-command with, at least, two arguments +foreach (subcommand IN ITEMS GET APPEND PREPEND REMOVE_ITEM REMOVE_AT TRANSFORM) + check_list_syntax (${subcommand} missing-arg "-DLIST_ARGUMENTS=${subcommand},ARG1") +endforeach() + +### sub-command with, at least, three arguments +foreach (subcommand IN ITEMS INSERT) + check_list_syntax (${subcommand} missing-arg "-DLIST_ARGUMENTS=${subcommand},ARG1,ARG2") +endforeach() + +# TRANSFORM sub-commands +set(RunCMake-stderr-file "TRANSFORM-missing-arg-stderr.txt") +foreach (action IN ITEMS APPEND PREPEND) + check_list_syntax (TRANSFORM-${action} missing-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,${action}") +endforeach() +check_list_syntax (TRANSFORM-REPLACE-1 missing-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,REPLACE,ARG2") +check_list_syntax (TRANSFORM-REPLACE-2 missing-arg "-DLIST_ARGUMENTS=TRANSFORM,ARG1,REPLACE") +unset(RunCMake-stderr-file) + + +run_cmake(GET-wrong-index1) +run_cmake(GET-wrong-index2) +run_cmake(GET-wrong-index3) +run_cmake(SUBLIST-wrong-argument1) +run_cmake(SUBLIST-wrong-argument2) +run_cmake(INSERT-wrong-index1) +run_cmake(INSERT-wrong-index2) +run_cmake(REMOVE_AT-wrong-index1) +run_cmake(REMOVE_AT-wrong-index2) +run_cmake(REMOVE_AT-wrong-index3) +run_cmake(FILTER-wrong-operator) +run_cmake(FILTER-wrong-regex) +run_cmake(TRANSFORM-wrong-action) +run_cmake(TRANSFORM-REPLACE-wrong-regex) +run_cmake(TRANSFORM-REPLACE-invalid-replace1) +run_cmake(TRANSFORM-REPLACE-invalid-replace2) +run_cmake(TRANSFORM-selector-REGEX-no-arguments) +run_cmake(TRANSFORM-selector-REGEX-wrong-regex) +run_cmake(TRANSFORM-selector-AT-no-arguments) +run_cmake(TRANSFORM-selector-AT-wrong-argument) +run_cmake(TRANSFORM-selector-AT-wrong-index) +run_cmake(TRANSFORM-selector-FOR-no-arguments) +run_cmake(TRANSFORM-selector-FOR-missing-arguments) +run_cmake(TRANSFORM-selector-FOR-wrong-argument) +run_cmake(TRANSFORM-selector-FOR-wrong-index) +run_cmake(TRANSFORM-selector-FOR-zero-step) +run_cmake(TRANSFORM-selector-FOR-negative-step) +run_cmake(TRANSFORM-selector-FOR-backwards-range) +run_cmake(SORT-wrong-option) +run_cmake(SORT-wrong-COMPARE-option) +run_cmake(SORT-wrong-CASE-option) +run_cmake(SORT-wrong-ORDER-option) +run_cmake(SORT-duplicate-COMPARE-option) +run_cmake(SORT-duplicate-CASE-option) +run_cmake(SORT-duplicate-ORDER-option) + + +function(check_list_execution name) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_VARIANT_DESCRIPTION " - ${name}") + run_cmake_with_options(generate -DLIST_TEST=${name}) + run_cmake_command(check "${CMAKE_COMMAND}" "-DRunCMake_SOURCE_DIR=${RunCMake_SOURCE_DIR}" -P "${RunCMake_TEST_BINARY_DIR}/${name}.cmake") +endfunction() + +check_list_execution (LENGTH) +check_list_execution (GET) +check_list_execution (JOIN) +check_list_execution (SUBLIST) +check_list_execution (FIND) +check_list_execution (APPEND) +check_list_execution (PREPEND) +check_list_execution (INSERT) +check_list_execution (POP_BACK) +check_list_execution (POP_FRONT) +check_list_execution (REMOVE_ITEM) +check_list_execution (REMOVE_AT) +check_list_execution (REMOVE_DUPLICATES) +check_list_execution (TRANSFORM-TOUPPER) +check_list_execution (TRANSFORM-TOLOWER) +check_list_execution (TRANSFORM-STRIP) +check_list_execution (TRANSFORM-APPEND) +check_list_execution (TRANSFORM-PREPEND) +check_list_execution (TRANSFORM-REPLACE) +check_list_execution (REVERSE) +check_list_execution (SORT) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option-stderr.txt new file mode 100644 index 0000000000..4f3121a361 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at SORT-duplicate-CASE-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,COMPARE:STRING,CASE:SENSITIVE,CASE:SENSITIVE> + + sub-command SORT, CASE option has been specified multiple times. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option.cmake new file mode 100644 index 0000000000..e09dc6ca07 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-CASE-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,COMPARE:STRING,CASE:SENSITIVE,CASE:SENSITIVE>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option-stderr.txt new file mode 100644 index 0000000000..fbb96bbb29 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at SORT-duplicate-COMPARE-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,COMPARE:STRING,COMPARE:NATURAL> + + sub-command SORT, COMPARE option has been specified multiple times. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option.cmake new file mode 100644 index 0000000000..cf8da0d32e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-COMPARE-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,COMPARE:STRING,COMPARE:NATURAL>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option-stderr.txt new file mode 100644 index 0000000000..b45034a7db --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at SORT-duplicate-ORDER-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,ORDER:ASCENDING,COMPARE:STRING,ORDER:DESCENDING,CASE:SENSITIVE> + + sub-command SORT, ORDER option has been specified multiple times. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option.cmake new file mode 100644 index 0000000000..3826072fdc --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-duplicate-ORDER-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,ORDER:ASCENDING,COMPARE:STRING,ORDER:DESCENDING,CASE:SENSITIVE>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option-stderr.txt new file mode 100644 index 0000000000..d36e63b1ec --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at SORT-wrong-CASE-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,COMPARE:STRING,CASE:WRONG_OPTION> + + sub-command SORT, an invalid CASE option has been specified: + "WRONG_OPTION". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option.cmake new file mode 100644 index 0000000000..58df9ea3dc --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-CASE-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,COMPARE:STRING,CASE:WRONG_OPTION>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option-stderr.txt new file mode 100644 index 0000000000..70a99c6419 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at SORT-wrong-COMPARE-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,COMPARE:WRONG_OPTION> + + sub-command SORT, an invalid COMPARE option has been specified: + "WRONG_OPTION". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option.cmake new file mode 100644 index 0000000000..73727bb416 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-COMPARE-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,COMPARE:WRONG_OPTION>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option-stderr.txt new file mode 100644 index 0000000000..2e23d8c4b0 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at SORT-wrong-ORDER-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,COMPARE:STRING,CASE:SENSITIVE,ORDER:WRONG_OPTION> + + sub-command SORT, an invalid ORDER option has been specified: + "WRONG_OPTION". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option.cmake new file mode 100644 index 0000000000..135c9350eb --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-ORDER-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,COMPARE:STRING,CASE:SENSITIVE,ORDER:WRONG_OPTION>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-option-result.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/SORT-wrong-option-stderr.txt new file mode 100644 index 0000000000..3c2d492508 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-option-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at SORT-wrong-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SORT,a;b,WRONG_OPTION> + + sub-command SORT, option "WRONG_OPTION" is invalid. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SORT-wrong-option.cmake b/Tests/RunCMake/GenEx-LIST/SORT-wrong-option.cmake new file mode 100644 index 0000000000..fca268b817 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT-wrong-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SORT,a;b,WRONG_OPTION>") diff --git a/Tests/RunCMake/GenEx-LIST/SORT.cmake.in b/Tests/RunCMake/GenEx-LIST/SORT.cmake.in new file mode 100644 index 0000000000..aca6691f90 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SORT.cmake.in @@ -0,0 +1,92 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(source_unsorted c/B.h a/c.h B/a.h) + +set(listvar ${source_unsorted}) +list(SORT listvar) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE INSENSITIVE ORDER ASCENDING COMPARE STRING) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:INSENSITIVE,ORDER:ASCENDING,COMPARE:STRING>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE INSENSITIVE ORDER DESCENDING COMPARE STRING) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:INSENSITIVE,ORDER:DESCENDING,COMPARE:STRING>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE SENSITIVE ORDER ASCENDING COMPARE STRING) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:SENSITIVE,ORDER:ASCENDING,COMPARE:STRING>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE SENSITIVE ORDER DESCENDING COMPARE STRING) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:SENSITIVE,ORDER:DESCENDING,COMPARE:STRING>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:INSENSITIVE,ORDER:ASCENDING,COMPARE:FILE_BASENAME>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:INSENSITIVE,ORDER:DESCENDING,COMPARE:FILE_BASENAME>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:SENSITIVE,ORDER:ASCENDING,COMPARE:FILE_BASENAME>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar ${source_unsorted}) +list(SORT listvar CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME) +set (output "$<LIST:SORT,c/B.h;a/c.h;B/a.h,CASE:SENSITIVE,ORDER:DESCENDING,COMPARE:FILE_BASENAME>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar 10.0 1.1 2.1 8.0 2.0 3.1) +list(SORT listvar CASE SENSITIVE ORDER DESCENDING COMPARE STRING) +set (output "$<LIST:SORT,10.0;1.1;2.1;8.0;2.0;3.1,CASE:SENSITIVE,ORDER:DESCENDING,COMPARE:STRING>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar 10.0 1.1 2.1 8.0 2.0 3.1) +list(SORT listvar CASE SENSITIVE ORDER DESCENDING COMPARE NATURAL) +set (output "$<LIST:SORT,10.0;1.1;2.1;8.0;2.0;3.1,CASE:SENSITIVE,ORDER:DESCENDING,COMPARE:NATURAL>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + +set(listvar 10.0 1.1 2.1 8.0 2.0 3.1) +list(SORT listvar CASE SENSITIVE ORDER ASCENDING COMPARE NATURAL) +set (output "$<LIST:SORT,10.0;1.1;2.1;8.0;2.0;3.1,CASE:SENSITIVE,ORDER:ASCENDING,COMPARE:NATURAL>") +if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:SORT..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1-result.txt b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1-stderr.txt b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1-stderr.txt new file mode 100644 index 0000000000..078f345e3f --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at SUBLIST-wrong-argument1.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SUBLIST,a;b;c,3,-1> + + begin index: 3 is out of range 0 - 2 +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1.cmake b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1.cmake new file mode 100644 index 0000000000..293c2ae977 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument1.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SUBLIST,a;b;c,3,-1>") diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2-result.txt b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2-stderr.txt b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2-stderr.txt new file mode 100644 index 0000000000..7271b30b3f --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at SUBLIST-wrong-argument2.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:SUBLIST,a;b;c,1,-2> + + length: -2 should be -1 or greater +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2.cmake b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2.cmake new file mode 100644 index 0000000000..9d1db53245 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST-wrong-argument2.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:SUBLIST,a;b;c,1,-2>") diff --git a/Tests/RunCMake/GenEx-LIST/SUBLIST.cmake.in b/Tests/RunCMake/GenEx-LIST/SUBLIST.cmake.in new file mode 100644 index 0000000000..9fcb6d50ab --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/SUBLIST.cmake.in @@ -0,0 +1,32 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar a b c d) + +list(SUBLIST listvar 1 2 reference) +set (output "$<LIST:SUBLIST,a;b;c;d,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(SUBLIST listvar 1 -1 reference) +set (output "$<LIST:SUBLIST,a;b;c;d,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(SUBLIST listvar 1 0 reference) +set (output "$<LIST:SUBLIST,a;b;c;d,1,0>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(SUBLIST listvar 1 5 reference) +set (output "$<LIST:SUBLIST,a;b;c;d,1,5>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:SUBLIST..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-APPEND.cmake.in b/Tests/RunCMake/GenEx-LIST/TRANSFORM-APPEND.cmake.in new file mode 100644 index 0000000000..a6529ec578 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-APPEND.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar alpha bravo charlie delta) + +list(TRANSFORM listvar APPEND "_A" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar APPEND "_A" AT 1 3 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A,AT,1,3>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar APPEND "_A" AT 1 -2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A,AT,1,-2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar APPEND "_A" FOR 1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A,FOR,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar APPEND "_A" FOR 1 -1 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A,FOR,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar APPEND "_A" FOR 1 -1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A,FOR,1,-1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar APPEND "_A" REGEX "(r|t)a" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,APPEND,_A,REGEX,(r|t)a>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:TRANSFORM,APPEND..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-PREPEND.cmake.in b/Tests/RunCMake/GenEx-LIST/TRANSFORM-PREPEND.cmake.in new file mode 100644 index 0000000000..5ec6acdcc8 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-PREPEND.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar alpha bravo charlie delta) + +list(TRANSFORM listvar PREPEND "P_" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar PREPEND "P_" AT 1 3 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_,AT,1,3>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar PREPEND "P_" AT 1 -2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_,AT,1,-2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar PREPEND "P_" FOR 1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_,FOR,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar PREPEND "P_" FOR 1 -1 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_,FOR,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar PREPEND "P_" FOR 1 -1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_,FOR,1,-1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar PREPEND "P_" REGEX "(r|t)a" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,PREPEND,P_,REGEX,(r|t)a>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:TRANSFORM,PREPEND..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1-stderr.txt new file mode 100644 index 0000000000..6674b30688 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TRANSFORM-REPLACE-invalid-replace1.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,REPLACE,\^a,b\\> + + sub-command TRANSFORM, action REPLACE: replace-expression ends in a + backslash. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1.cmake new file mode 100644 index 0000000000..d45e1fdaf4 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace1.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,REPLACE,^a,b\\>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2-stderr.txt new file mode 100644 index 0000000000..2351b72eb1 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TRANSFORM-REPLACE-invalid-replace2.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,REPLACE,\^a,\\b> + + sub-command TRANSFORM, action REPLACE: Unknown escape "\\b" in + replace-expression. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2.cmake new file mode 100644 index 0000000000..b800f24f2e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-invalid-replace2.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,REPLACE,^a,\\b>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex-stderr.txt new file mode 100644 index 0000000000..617c3d6d04 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-REPLACE-wrong-regex.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,REPLACE,\(a,b> + + sub-command TRANSFORM, action REPLACE: Failed to compile regex "\(a". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex.cmake new file mode 100644 index 0000000000..941e3e7ff8 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE-wrong-regex.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,REPLACE,(a,b>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE.cmake.in b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE.cmake.in new file mode 100644 index 0000000000..5fba23109c --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-REPLACE.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar alpha bravo charlie delta) + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" AT 1 3 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1,AT,1,3>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" AT 1 -2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1,AT,1,-2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" FOR 1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1,FOR,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" FOR 1 -1 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1,FOR,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" FOR 1 -1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1,FOR,1,-1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar REPLACE "(.+a)$" "\\1_\\1" REGEX "(r|t)a" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,REPLACE,(.+a)$,\1_\1,REGEX,(r|t)a>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:TRANSFORM,REPLACE..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-STRIP.cmake.in b/Tests/RunCMake/GenEx-LIST/TRANSFORM-STRIP.cmake.in new file mode 100644 index 0000000000..860faec771 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-STRIP.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar " alpha" "bravo " " charlie " delta) + +list(TRANSFORM listvar STRIP OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar STRIP AT 1 3 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP,AT,1,3>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar STRIP AT 1 -2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP,AT,1,-2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar STRIP FOR 1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP,FOR,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar STRIP FOR 1 -1 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP,FOR,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar STRIP FOR 1 -1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP,FOR,1,-1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar STRIP REGEX "(r|t)a" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM, alpha;bravo ; charlie ;delta,STRIP,REGEX,(r|t)a>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:TRANSFORM,STRIP..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-TOLOWER.cmake.in b/Tests/RunCMake/GenEx-LIST/TRANSFORM-TOLOWER.cmake.in new file mode 100644 index 0000000000..43e99556c6 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-TOLOWER.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar ALPHA BRAVO CHARLIE DELTA) + +list(TRANSFORM listvar TOLOWER OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOLOWER AT 1 3 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER,AT,1,3>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOLOWER AT 1 -2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER,AT,1,-2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOLOWER FOR 1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER,FOR,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOLOWER FOR 1 -1 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER,FOR,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOLOWER FOR 1 -1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER,FOR,1,-1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOLOWER REGEX "(R|T)A" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,ALPHA;BRAVO;CHARLIE;DELTA,TOLOWER,REGEX,(R|T)A>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:TRANSFORM,TOLOWER..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-TOUPPER.cmake.in b/Tests/RunCMake/GenEx-LIST/TRANSFORM-TOUPPER.cmake.in new file mode 100644 index 0000000000..be2bc3039c --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-TOUPPER.cmake.in @@ -0,0 +1,50 @@ + +include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") +unset (errors) + +set(listvar alpha bravo charlie delta) + +list(TRANSFORM listvar TOUPPER OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOUPPER AT 1 3 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER,AT,1,3>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOUPPER AT 1 -2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER,AT,1,-2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOUPPER FOR 1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER,FOR,1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOUPPER FOR 1 -1 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER,FOR,1,-1>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOUPPER FOR 1 -1 2 OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER,FOR,1,-1,2>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + +list(TRANSFORM listvar TOUPPER REGEX "(r|t)a" OUTPUT_VARIABLE reference) +set (output "$<LIST:TRANSFORM,alpha;bravo;charlie;delta,TOUPPER,REGEX,(r|t)a>") +if (NOT output STREQUAL reference) + list (APPEND errors "returns bad value: ${output}") +endif() + + +check_errors("LIST:TRANSFORM,TOUPPER..." ${errors}) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-missing-arg-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-missing-arg-stderr.txt new file mode 100644 index 0000000000..46e36c3bcc --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-missing-arg-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at missing-arg.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,ARG1,[A-Z]+(,ARG[0-9])?> + + sub-command TRANSFORM, action [A-Z]+ expects (1|2) argument\(s\). +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments-stderr.txt new file mode 100644 index 0000000000..69b4915e74 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-AT-no-arguments.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,TOUPPER,AT> + + sub-command TRANSFORM, selector AT expects at least one numeric value. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments.cmake new file mode 100644 index 0000000000..2447511598 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-no-arguments.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,TOUPPER,AT>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument-stderr.txt new file mode 100644 index 0000000000..40007a181c --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-AT-wrong-argument.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,TOUPPER,AT,0,1x,2> + + sub-command TRANSFORM, selector AT: '1x': unexpected argument. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument.cmake new file mode 100644 index 0000000000..49f4e908d8 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-argument.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,TOUPPER,AT,0,1x,2>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index-stderr.txt new file mode 100644 index 0000000000..66085ab862 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-AT-wrong-index.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,TOUPPER,AT,0,3,2> + + sub-command TRANSFORM, selector AT, index: 3 out of range \(-3, 2\). +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index.cmake new file mode 100644 index 0000000000..fd6c3ed1ef --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-AT-wrong-index.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,TOUPPER,AT,0,3,2>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range-stderr.txt new file mode 100644 index 0000000000..77cffdc831 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TRANSFORM-selector-FOR-backwards-range.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,2,0> + + sub-command TRANSFORM, selector FOR expects <start> to be no greater than + <stop> \(2 > 0\) +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range.cmake new file mode 100644 index 0000000000..17f57f586e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-backwards-range.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,2,0>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments-stderr.txt new file mode 100644 index 0000000000..a9de7f8070 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-FOR-missing-arguments.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,TOUPPER,FOR,0> + + sub-command TRANSFORM, selector FOR expects, at least, two arguments. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments.cmake new file mode 100644 index 0000000000..5ae481aac2 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-missing-arguments.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,TOUPPER,FOR,0>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step-stderr.txt new file mode 100644 index 0000000000..9c81de4bf6 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TRANSFORM-selector-FOR-negative-step.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,2,-1> + + sub-command TRANSFORM, selector FOR expects positive numeric value for + <step>. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step.cmake new file mode 100644 index 0000000000..b8e6433617 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-negative-step.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,2,-1>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments-stderr.txt new file mode 100644 index 0000000000..d31f171bfc --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-FOR-no-arguments.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,TOUPPER,FOR> + + sub-command TRANSFORM, selector FOR expects, at least, two arguments. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments.cmake new file mode 100644 index 0000000000..6545ff95e6 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-no-arguments.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,TOUPPER,FOR>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument-stderr.txt new file mode 100644 index 0000000000..727be10714 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-FOR-wrong-argument.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,1x,2> + + sub-command TRANSFORM, selector FOR expects, at least, two numeric values. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument.cmake new file mode 100644 index 0000000000..a50b62c1d8 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-argument.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,1x,2>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index-stderr.txt new file mode 100644 index 0000000000..664e35a591 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-FOR-wrong-index.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,4,2> + + sub-command TRANSFORM, selector FOR, index: 4 out of range \(-3, 2\). +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index.cmake new file mode 100644 index 0000000000..f35bfbf027 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-wrong-index.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,4,2>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step-stderr.txt new file mode 100644 index 0000000000..e542fbfcdb --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TRANSFORM-selector-FOR-zero-step.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,2,0> + + sub-command TRANSFORM, selector FOR expects positive numeric value for + <step>. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step.cmake new file mode 100644 index 0000000000..2bfaab0907 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-FOR-zero-step.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,TOUPPER,FOR,0,2,0>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments-stderr.txt new file mode 100644 index 0000000000..079172b03d --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TRANSFORM-selector-REGEX-no-arguments.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,TOUPPER,REGEX> + + sub-command TRANSFORM, selector REGEX expects 'regular expression' + argument. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments.cmake new file mode 100644 index 0000000000..1f802b757e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-no-arguments.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,TOUPPER,REGEX>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex-stderr.txt new file mode 100644 index 0000000000..3fe2b014a7 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at TRANSFORM-selector-REGEX-wrong-regex.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b,TOUPPER,REGEX,\(a> + + sub-command TRANSFORM, selector REGEX failed to compile regex "\(a". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex.cmake new file mode 100644 index 0000000000..164809206c --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-selector-REGEX-wrong-regex.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b,TOUPPER,REGEX,(a>") diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-unexpected-arg-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-unexpected-arg-stderr.txt new file mode 100644 index 0000000000..04e9df1679 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-unexpected-arg-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at unexpected-arg.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,ARG1,[A-Z_]+(,[A-Z0-9]+)+> + + sub-command TRANSFORM, '[A-Z0-9]+': unexpected argument\(s\). +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action-result.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action-stderr.txt b/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action-stderr.txt new file mode 100644 index 0000000000..1c30c4f903 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action-stderr.txt @@ -0,0 +1,7 @@ +CMake Error at TRANSFORM-wrong-action.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:TRANSFORM,a;b;c,WRONG_ACTION> + sub-command TRANSFORM, WRONG_ACTION invalid action. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action.cmake b/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action.cmake new file mode 100644 index 0000000000..fba6c90f43 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/TRANSFORM-wrong-action.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:TRANSFORM,a;b;c,WRONG_ACTION>") diff --git a/Tests/RunCMake/GenEx-LIST/bad-option-result.txt b/Tests/RunCMake/GenEx-LIST/bad-option-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/bad-option-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/bad-option-stderr.txt b/Tests/RunCMake/GenEx-LIST/bad-option-stderr.txt new file mode 100644 index 0000000000..37048c5f0e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/bad-option-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at bad-option.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:BAD_OPTION,ARG> + + BAD_OPTION: invalid option. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/bad-option.cmake b/Tests/RunCMake/GenEx-LIST/bad-option.cmake new file mode 100644 index 0000000000..d1dc85f276 --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/bad-option.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:BAD_OPTION,ARG>") diff --git a/Tests/RunCMake/GenEx-LIST/check_errors.cmake b/Tests/RunCMake/GenEx-LIST/check_errors.cmake new file mode 100644 index 0000000000..7e60fc725e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/check_errors.cmake @@ -0,0 +1,13 @@ + +function (CHECK_ERRORS command) + set (errors ${ARGN}) + set (command "$<${command}>") + if (errors) + string (LENGTH "${command}" length) + math (EXPR count "${length} + 2") + string (REPEAT " " ${count} shift) + list (TRANSFORM errors PREPEND "${shift}") + list (JOIN errors "\n" msg) + message (FATAL_ERROR "${command}: ${msg}") + endif() +endfunction() diff --git a/Tests/RunCMake/GenEx-LIST/generate.cmake b/Tests/RunCMake/GenEx-LIST/generate.cmake new file mode 100644 index 0000000000..92cdca2a5d --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/generate.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT "${LIST_TEST}.cmake" INPUT "${LIST_TEST}.cmake.in") diff --git a/Tests/RunCMake/GenEx-LIST/missing-arg-result.txt b/Tests/RunCMake/GenEx-LIST/missing-arg-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/missing-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/missing-arg-stderr.txt b/Tests/RunCMake/GenEx-LIST/missing-arg-stderr.txt new file mode 100644 index 0000000000..c7cbe4b13a --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/missing-arg-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at missing-arg.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:[A-Z_]+,.+> + + \$<LIST:[A-Z_]+> expression requires at least (two|three) parameters. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/missing-arg.cmake b/Tests/RunCMake/GenEx-LIST/missing-arg.cmake new file mode 100644 index 0000000000..48b26e13af --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/missing-arg.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:${LIST_ARGUMENTS}>") diff --git a/Tests/RunCMake/GenEx-LIST/no-arguments-result.txt b/Tests/RunCMake/GenEx-LIST/no-arguments-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/no-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/no-arguments-stderr.txt b/Tests/RunCMake/GenEx-LIST/no-arguments-stderr.txt new file mode 100644 index 0000000000..ee782ecfde --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/no-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at no-arguments.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:> + + \$<LIST> expression requires at least two parameters. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/no-arguments.cmake b/Tests/RunCMake/GenEx-LIST/no-arguments.cmake new file mode 100644 index 0000000000..f704e2b76e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/no-arguments.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:>") diff --git a/Tests/RunCMake/GenEx-LIST/unexpected-arg-result.txt b/Tests/RunCMake/GenEx-LIST/unexpected-arg-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/unexpected-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LIST/unexpected-arg-stderr.txt b/Tests/RunCMake/GenEx-LIST/unexpected-arg-stderr.txt new file mode 100644 index 0000000000..a7b1f25e1e --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/unexpected-arg-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at unexpected-arg.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$<LIST:[A-Z_]+,.+> + + \$<LIST:[A-Z_]+(,[A-Z_]+)?> expression requires exactly (one|two|three) parameters?. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LIST/unexpected-arg.cmake b/Tests/RunCMake/GenEx-LIST/unexpected-arg.cmake new file mode 100644 index 0000000000..48b26e13af --- /dev/null +++ b/Tests/RunCMake/GenEx-LIST/unexpected-arg.cmake @@ -0,0 +1,2 @@ + +file(GENERATE OUTPUT result.txt CONTENT "$<LIST:${LIST_ARGUMENTS}>") diff --git a/Tests/RunCMake/IncludeWhatYouUse/C-error-Build-result.txt b/Tests/RunCMake/IncludeWhatYouUse/C-error-Build-result.txt new file mode 100644 index 0000000000..d197c913c2 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/C-error-Build-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/IncludeWhatYouUse/C-error-Build-stdout.txt b/Tests/RunCMake/IncludeWhatYouUse/C-error-Build-stdout.txt new file mode 100644 index 0000000000..cb7467705e --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/C-error-Build-stdout.txt @@ -0,0 +1,4 @@ +Warning: include-what-you-use reported diagnostics: +should add these lines: +* +#include <\.\.\.> diff --git a/Tests/RunCMake/IncludeWhatYouUse/C-error.cmake b/Tests/RunCMake/IncludeWhatYouUse/C-error.cmake new file mode 100644 index 0000000000..d5230bbf8c --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/C-error.cmake @@ -0,0 +1,3 @@ +enable_language(C) +set(CMAKE_C_INCLUDE_WHAT_YOU_USE "${PSEUDO_IWYU}" -Xiwyu --error) +add_executable(main main.c) diff --git a/Tests/RunCMake/IncludeWhatYouUse/CXX-error-Build-result.txt b/Tests/RunCMake/IncludeWhatYouUse/CXX-error-Build-result.txt new file mode 100644 index 0000000000..d197c913c2 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/CXX-error-Build-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/IncludeWhatYouUse/CXX-error-Build-stdout.txt b/Tests/RunCMake/IncludeWhatYouUse/CXX-error-Build-stdout.txt new file mode 100644 index 0000000000..cb7467705e --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/CXX-error-Build-stdout.txt @@ -0,0 +1,4 @@ +Warning: include-what-you-use reported diagnostics: +should add these lines: +* +#include <\.\.\.> diff --git a/Tests/RunCMake/IncludeWhatYouUse/CXX-error.cmake b/Tests/RunCMake/IncludeWhatYouUse/CXX-error.cmake new file mode 100644 index 0000000000..1d10a550d4 --- /dev/null +++ b/Tests/RunCMake/IncludeWhatYouUse/CXX-error.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "$<1:${PSEUDO_IWYU}>" -Xiwyu --error) +add_executable(main main.cxx) diff --git a/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake b/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake index 8f99eb1047..8ec24be5ca 100644 --- a/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake +++ b/Tests/RunCMake/IncludeWhatYouUse/RunCMakeTest.cmake @@ -16,6 +16,8 @@ endfunction() run_iwyu(C) run_iwyu(CXX) +run_iwyu(C-error) +run_iwyu(CXX-error) if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") run_iwyu(C-launch) run_iwyu(CXX-launch) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 8e85f6cf46..18dde944d7 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -47,6 +47,8 @@ function(run_cmake test) elseif(EXISTS ${top_src}/${test}-${o}.txt) file(READ ${top_src}/${test}-${o}.txt expect_${o}) string(REGEX REPLACE "\n+$" "" expect_${o} "${expect_${o}}") + elseif(DEFINED RunCMake_TEST_EXPECT_${o}) + string(REGEX REPLACE "\n+$" "" expect_${o} "${RunCMake_TEST_EXPECT_${o}}") else() unset(expect_${o}) endif() @@ -175,7 +177,7 @@ function(run_cmake test) "|Your license to use PGI[^\n]*expired" "|Please obtain a new version at" "|contact PGI Sales at" - "|icp?c: remark #10441: The Intel\\(R\\) C\\+\\+ Compiler Classic \\(ICC\\) is deprecated" + "|ic(p?c|l): remark #10441: The Intel\\(R\\) C\\+\\+ Compiler Classic \\(ICC\\) is deprecated" "|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:" "|[^\n]*xcodebuild[^\n]*DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default" diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d.txt b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt index fbdecc072b..2588181b8b 100644 --- a/Tests/RunCMake/TransformDepfile/deps-unix.d.txt +++ b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt @@ -1,8 +1,8 @@ subdir/out1 \ /home/build/out2: \ - subdir/in1 \ - /home/build/in2 + /home/build/in2 \ + subdir/in1 subdir/out3 \ /home/build/out4: \ - subdir/in3 \ - /home/build/in4 + /home/build/in4 \ + subdir/in3 diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.d.txt b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt index e09ae375a8..805a4c8362 100644 --- a/Tests/RunCMake/TransformDepfile/deps-windows.d.txt +++ b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt @@ -1,8 +1,8 @@ subdir/out1 \ C:/build/out2: \ - subdir/in1 \ - C:/build/in2 + C:/build/in2 \ + subdir/in1 subdir/out3 \ C:/build/out4: \ - subdir/in3 \ - C:/build/in4 + C:/build/in4 \ + subdir/in3 diff --git a/Tests/RunCMake/VS10Project/CMakeInputs-check.cmake b/Tests/RunCMake/VS10Project/CMakeInputs-check.cmake new file mode 100644 index 0000000000..a125574d8e --- /dev/null +++ b/Tests/RunCMake/VS10Project/CMakeInputs-check.cmake @@ -0,0 +1,25 @@ +set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/ZERO_CHECK.vcxproj") +if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") + return() +endif() + +set(found_CMakeInputs 0) +file(STRINGS "${vcProjectFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*CMakeInputs.cmake") + set(rule "${CMAKE_MATCH_1}") + if(NOT rule STREQUAL "None") + set(RunCMake_TEST_FAILED "CMakeInputs.cmake referenced as ${rule} instead of None") + return() + endif() + if(found_CMakeInputs) + set(RunCMake_TEST_FAILED "CMakeInputs.cmake referenced multiple times") + return() + endif() + set(found_CMakeInputs 1) + endif() +endforeach() +if(NOT found_CMakeInputs) + set(RunCMake_TEST_FAILED "CMakeInputs.cmake not referenced") +endif() diff --git a/Tests/RunCMake/VS10Project/CMakeInputs.cmake b/Tests/RunCMake/VS10Project/CMakeInputs.cmake new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/Tests/RunCMake/VS10Project/CMakeInputs.cmake diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 669049a737..cb1a5d5403 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -7,6 +7,7 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREA run_cmake(LanguageStandard) endif() +run_cmake(CMakeInputs) run_cmake(CustomCommandGenex) if(NOT RunCMake_GENERATOR MATCHES "^Visual Studio 1[1-5] ") run_cmake(CustomCommandParallel) diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash index 856a6ea7c9..5a4f11a0b6 100755 --- a/Utilities/Scripts/update-libarchive.bash +++ b/Utilities/Scripts/update-libarchive.bash @@ -8,7 +8,7 @@ readonly name="LibArchive" readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>" readonly subtree="Utilities/cmlibarchive" readonly repo="https://github.com/libarchive/libarchive.git" -readonly tag="v3.6.0" +readonly tag="v3.6.2" readonly shortlog=false readonly paths=" CMakeLists.txt diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index b38e6530a3..027de5c589 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -238,7 +238,7 @@ OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON) OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON) OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON) OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON) -OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON) +OPTION(ENABLE_LIBGCC "Enable the use of the system LibGCC library if found" ON) # CNG is used for encrypt/decrypt Zip archives on Windows. OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON) @@ -257,7 +257,7 @@ OPTION(ENABLE_INSTALL "Enable installing of libraries" ON) SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support") SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)") -SET(WINDOWS_VERSION "WIN7" CACHE STRING "Set Windows version to use (Windows only)") +SET(WINDOWS_VERSION "WIN10" CACHE STRING "Set Windows version to use (Windows only)") IF(ENABLE_COVERAGE) include(LibarchiveCodeCoverage) @@ -268,7 +268,11 @@ IF(ENABLE_TEST) ENDIF(ENABLE_TEST) IF(WIN32) - IF(WINDOWS_VERSION STREQUAL "WIN8") + IF(WINDOWS_VERSION STREQUAL "WIN10") + SET(NTDDI_VERSION 0x0A000000) + SET(_WIN32_WINNT 0x0A00) + SET(WINVER 0x0A00) + ELSEIF(WINDOWS_VERSION STREQUAL "WIN8") SET(NTDDI_VERSION 0x06020000) SET(_WIN32_WINNT 0x0602) SET(WINVER 0x0602) @@ -292,12 +296,12 @@ IF(WIN32) SET(NTDDI_VERSION 0x05010000) SET(_WIN32_WINNT 0x0501) SET(WINVER 0x0501) - ELSE(WINDOWS_VERSION STREQUAL "WIN8") + ELSE(WINDOWS_VERSION STREQUAL "WIN10") # Default to Windows Server 2003 API if we don't recognize the specifier SET(NTDDI_VERSION 0x05020000) SET(_WIN32_WINNT 0x0502) SET(WINVER 0x0502) - ENDIF(WINDOWS_VERSION STREQUAL "WIN8") + ENDIF(WINDOWS_VERSION STREQUAL "WIN10") ENDIF(WIN32) IF(MSVC) @@ -632,8 +636,15 @@ IF(ENABLE_ZSTD) SET(ZSTD_FIND_QUIETLY TRUE) ENDIF (ZSTD_INCLUDE_DIR) - FIND_PATH(ZSTD_INCLUDE_DIR zstd.h) - FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd) + IF(0) # CMake does not let pkg-config override its search paths. + IF(UNIX) + FIND_PACKAGE(PkgConfig QUIET) + PKG_SEARCH_MODULE(PC_ZSTD libzstd) + ENDIF() + ENDIF() + + FIND_PATH(ZSTD_INCLUDE_DIR zstd.h HINTS ${PC_ZSTD_INCLUDEDIR} ${PC_ZSTD_INCLUDE_DIRS}) + FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd HINTS ${PC_ZSTD_LIBDIR} ${PC_ZSTD_LIBRARY_DIRS}) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR) ELSE(ENABLE_ZSTD) @@ -1284,9 +1295,10 @@ IF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$" # # If requested, try finding library for PCREPOSIX # - IF(ENABLE_LibGCC) - FIND_PACKAGE(LibGCC) + IF(ENABLE_LIBGCC) + FIND_PACKAGE(LIBGCC) ELSE() + MESSAGE(FATAL_ERROR "libgcc not found.") SET(LIBGCC_FOUND FALSE) # Override cached value ENDIF() IF(ENABLE_PCREPOSIX) @@ -1996,6 +2008,19 @@ CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512") +IF(0) # CMake does not build libarchive's shared library. +# Check visibility annotations +SET(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") +SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fvisibility=hidden -Werror") +CHECK_C_SOURCE_COMPILES("void __attribute__((visibility(\"default\"))) foo(void); +int main() { return 0; }" HAVE_VISIBILITY_ATTR) +IF (HAVE_VISIBILITY_ATTR) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") + ADD_DEFINITIONS(-D__LIBARCHIVE_ENABLE_VISIBILITY) +ENDIF(HAVE_VISIBILITY_ATTR) +SET(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") +ENDIF() + # Generate "config.h" from "build/cmake/config.h.in" CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake b/Utilities/cmlibarchive/build/cmake/FindLIBGCC.cmake index 7985f2b003..7985f2b003 100644 --- a/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake +++ b/Utilities/cmlibarchive/build/cmake/FindLIBGCC.cmake diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in index 72467a5461..e44a514080 100644 --- a/Utilities/cmlibarchive/build/cmake/config.h.in +++ b/Utilities/cmlibarchive/build/cmake/config.h.in @@ -147,13 +147,13 @@ #cmakedefine ARCHIVE_XATTR_LINUX 1 /* Version number of bsdcpio */ -#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}" +#cmakedefine BSDCPIO_VERSION_STRING "@BSDCPIO_VERSION_STRING@" /* Version number of bsdtar */ -#cmakedefine BSDTAR_VERSION_STRING "${BSDTAR_VERSION_STRING}" +#cmakedefine BSDTAR_VERSION_STRING "@BSDTAR_VERSION_STRING@" /* Version number of bsdcat */ -#cmakedefine BSDCAT_VERSION_STRING "${BSDCAT_VERSION_STRING}" +#cmakedefine BSDCAT_VERSION_STRING "@BSDCAT_VERSION_STRING@" /* Define to 1 if you have the `acl_create_entry' function. */ #cmakedefine HAVE_ACL_CREATE_ENTRY 1 @@ -1012,13 +1012,13 @@ #cmakedefine HAVE__MKGMTIME64 1 /* Define as const if the declaration of iconv() needs const. */ -#define ICONV_CONST ${ICONV_CONST} +#define ICONV_CONST @ICONV_CONST@ /* Version number of libarchive as a single integer */ -#cmakedefine LIBARCHIVE_VERSION_NUMBER "${LIBARCHIVE_VERSION_NUMBER}" +#cmakedefine LIBARCHIVE_VERSION_NUMBER "@LIBARCHIVE_VERSION_NUMBER@" /* Version number of libarchive */ -#cmakedefine LIBARCHIVE_VERSION_STRING "${LIBARCHIVE_VERSION_STRING}" +#cmakedefine LIBARCHIVE_VERSION_STRING "@LIBARCHIVE_VERSION_STRING@" /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ @@ -1036,7 +1036,7 @@ #cmakedefine NO_MINUS_C_MINUS_O 1 /* The size of `wchar_t', as computed by sizeof. */ -#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T} +#cmakedefine SIZEOF_WCHAR_T @SIZEOF_WCHAR_T@ /* Define to 1 if strerror_r returns char *. */ #cmakedefine STRERROR_R_CHAR_P 1 @@ -1072,56 +1072,56 @@ #endif /* SAFE_TO_DEFINE_EXTENSIONS */ /* Version number of package */ -#cmakedefine VERSION "${VERSION}" +#cmakedefine VERSION "@VERSION@" /* Number of bits in a file offset, on hosts where this is settable. */ -#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} +#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #cmakedefine _LARGEFILE_SOURCE 1 /* Define for large files, on AIX-style hosts. */ -#cmakedefine _LARGE_FILES ${_LARGE_FILES} +#cmakedefine _LARGE_FILES @_LARGE_FILES@ /* Define to control Windows SDK version */ #ifndef NTDDI_VERSION -#cmakedefine NTDDI_VERSION ${NTDDI_VERSION} +#cmakedefine NTDDI_VERSION @NTDDI_VERSION@ #endif // NTDDI_VERSION #ifndef _WIN32_WINNT -#cmakedefine _WIN32_WINNT ${_WIN32_WINNT} +#cmakedefine _WIN32_WINNT @_WIN32_WINNT@ #endif // _WIN32_WINNT #ifndef WINVER -#cmakedefine WINVER ${WINVER} +#cmakedefine WINVER @WINVER@ #endif // WINVER /* Define to empty if `const' does not conform to ANSI C. */ -#cmakedefine const ${const} +#cmakedefine const @const@ /* Define to `int' if <sys/types.h> doesn't define. */ -#cmakedefine gid_t ${gid_t} +#cmakedefine gid_t @gid_t@ /* Define to `unsigned long' if <sys/types.h> does not define. */ -#cmakedefine id_t ${id_t} +#cmakedefine id_t @id_t@ /* Define to `int' if <sys/types.h> does not define. */ -#cmakedefine mode_t ${mode_t} +#cmakedefine mode_t @mode_t@ /* Define to `long long' if <sys/types.h> does not define. */ -#cmakedefine off_t ${off_t} +#cmakedefine off_t @off_t@ /* Define to `int' if <sys/types.h> doesn't define. */ -#cmakedefine pid_t ${pid_t} +#cmakedefine pid_t @pid_t@ /* Define to `unsigned int' if <sys/types.h> does not define. */ -#cmakedefine size_t ${size_t} +#cmakedefine size_t @size_t@ /* Define to `int' if <sys/types.h> does not define. */ -#cmakedefine ssize_t ${ssize_t} +#cmakedefine ssize_t @ssize_t@ /* Define to `int' if <sys/types.h> doesn't define. */ -#cmakedefine uid_t ${uid_t} +#cmakedefine uid_t @uid_t@ #include <cm3p/kwiml/int.h> diff --git a/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in b/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in index 4b631e635c..1f51e77f16 100644 --- a/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in +++ b/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in @@ -10,3 +10,4 @@ Cflags: -I${includedir} Cflags.private: -DLIBARCHIVE_STATIC Libs: -L${libdir} -larchive Libs.private: @LIBS@ +Requires.private: @LIBSREQUIRED@ diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version index 102ec29cb7..1af1bec7bb 100644 --- a/Utilities/cmlibarchive/build/version +++ b/Utilities/cmlibarchive/build/version @@ -1 +1 @@ -3006000 +3006002 diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt index feb8697805..bee69c23e2 100644 --- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt @@ -5,6 +5,10 @@ # ############################################ +if (ANDROID) + include_directories(${PROJECT_SOURCE_DIR}/contrib/android/include) +endif() + # Public headers SET(include_HEADERS archive.h @@ -78,6 +82,7 @@ SET(libarchive_SOURCES archive_read_set_format.c archive_read_set_options.c archive_read_support_filter_all.c + archive_read_support_filter_by_code.c archive_read_support_filter_bzip2.c archive_read_support_filter_compress.c archive_read_support_filter_gzip.c diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h index ac01738235..180f3e4cbd 100644 --- a/Utilities/cmlibarchive/libarchive/archive.h +++ b/Utilities/cmlibarchive/libarchive/archive.h @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3006000 +#define ARCHIVE_VERSION_NUMBER 3006002 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -120,6 +120,8 @@ typedef ssize_t la_ssize_t; # define __LA_DECL __declspec(dllimport) # endif # endif +#elif defined __LIBARCHIVE_ENABLE_VISIBILITY +# define __LA_DECL __attribute__((visibility("default"))) #else /* Static libraries or non-Windows needs no special declaration. */ # define __LA_DECL @@ -152,7 +154,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.6.0" +#define ARCHIVE_VERSION_ONLY_STRING "3.6.2" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/Utilities/cmlibarchive/libarchive/archive_digest.c b/Utilities/cmlibarchive/libarchive/archive_digest.c index 410df01563..3361b19ada 100644 --- a/Utilities/cmlibarchive/libarchive/archive_digest.c +++ b/Utilities/cmlibarchive/libarchive/archive_digest.c @@ -49,16 +49,16 @@ * Initialize a Message digest. */ static int -win_crypto_init(Digest_CTX *ctx, ALG_ID algId) +win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId) { ctx->valid = 0; if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + prov, CRYPT_VERIFYCONTEXT)) { if (GetLastError() != (DWORD)NTE_BAD_KEYSET) return (ARCHIVE_FAILED); if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_NEWKEYSET)) + prov, CRYPT_NEWKEYSET)) return (ARCHIVE_FAILED); } @@ -243,7 +243,8 @@ __archive_md5init(archive_md5_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); - EVP_DigestInit(*ctx, EVP_md5()); + if (!EVP_DigestInit(*ctx, EVP_md5())) + return (ARCHIVE_FAILED); return (ARCHIVE_OK); } @@ -275,7 +276,7 @@ __archive_md5final(archive_md5_ctx *ctx, void *md) static int __archive_md5init(archive_md5_ctx *ctx) { - return (win_crypto_init(ctx, CALG_MD5)); + return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5)); } static int @@ -434,7 +435,8 @@ __archive_ripemd160init(archive_rmd160_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); - EVP_DigestInit(*ctx, EVP_ripemd160()); + if (!EVP_DigestInit(*ctx, EVP_ripemd160())) + return (ARCHIVE_FAILED); return (ARCHIVE_OK); } @@ -624,7 +626,8 @@ __archive_sha1init(archive_sha1_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); - EVP_DigestInit(*ctx, EVP_sha1()); + if (!EVP_DigestInit(*ctx, EVP_sha1())) + return (ARCHIVE_FAILED); return (ARCHIVE_OK); } @@ -656,7 +659,7 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md) static int __archive_sha1init(archive_sha1_ctx *ctx) { - return (win_crypto_init(ctx, CALG_SHA1)); + return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1)); } static int @@ -887,7 +890,8 @@ __archive_sha256init(archive_sha256_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); - EVP_DigestInit(*ctx, EVP_sha256()); + if (!EVP_DigestInit(*ctx, EVP_sha256())) + return (ARCHIVE_FAILED); return (ARCHIVE_OK); } @@ -915,7 +919,7 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md) static int __archive_sha256init(archive_sha256_ctx *ctx) { - return (win_crypto_init(ctx, CALG_SHA_256)); + return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256)); } static int @@ -1122,7 +1126,8 @@ __archive_sha384init(archive_sha384_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); - EVP_DigestInit(*ctx, EVP_sha384()); + if (!EVP_DigestInit(*ctx, EVP_sha384())) + return (ARCHIVE_FAILED); return (ARCHIVE_OK); } @@ -1150,7 +1155,7 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md) static int __archive_sha384init(archive_sha384_ctx *ctx) { - return (win_crypto_init(ctx, CALG_SHA_384)); + return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384)); } static int @@ -1381,7 +1386,8 @@ __archive_sha512init(archive_sha512_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); - EVP_DigestInit(*ctx, EVP_sha512()); + if (!EVP_DigestInit(*ctx, EVP_sha512())) + return (ARCHIVE_FAILED); return (ARCHIVE_OK); } @@ -1409,7 +1415,7 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md) static int __archive_sha512init(archive_sha512_ctx *ctx) { - return (win_crypto_init(ctx, CALG_SHA_512)); + return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512)); } static int diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c index ca7a4bdb50..ae6dc33361 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry.c @@ -568,6 +568,13 @@ archive_entry_nlink(struct archive_entry *entry) return (entry->ae_stat.aest_nlink); } +/* Instead, our caller could have chosen a specific encoding + * (archive_mstring_get_mbs, archive_mstring_get_utf8, + * archive_mstring_get_wcs). So we should try multiple + * encodings. Try mbs first because of history, even though + * utf8 might be better for pathname portability. + * Also omit wcs because of type mismatch (char * versus wchar *) + */ const char * archive_entry_pathname(struct archive_entry *entry) { @@ -575,6 +582,13 @@ archive_entry_pathname(struct archive_entry *entry) if (archive_mstring_get_mbs( entry->archive, &entry->ae_pathname, &p) == 0) return (p); +#if HAVE_EILSEQ /*{*/ + if (errno == EILSEQ) { + if (archive_mstring_get_utf8( + entry->archive, &entry->ae_pathname, &p) == 0) + return (p); + } +#endif /*}*/ if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index 221ef80ee8..91ef0c97e4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3006000 +#define ARCHIVE_VERSION_NUMBER 3006002 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -122,6 +122,8 @@ typedef ssize_t la_ssize_t; # define __LA_DECL __declspec(dllimport) # endif # endif +#elif defined __LIBARCHIVE_ENABLE_VISIBILITY +# define __LA_DECL __attribute__((visibility("default"))) #else /* Static libraries on all platforms and shared libraries on non-Windows. */ # define __LA_DECL diff --git a/Utilities/cmlibarchive/libarchive/archive_hmac.c b/Utilities/cmlibarchive/libarchive/archive_hmac.c index 2a9d04c8d8..012fe15962 100644 --- a/Utilities/cmlibarchive/libarchive/archive_hmac.c +++ b/Utilities/cmlibarchive/libarchive/archive_hmac.c @@ -230,10 +230,23 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM params[2]; + + EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + *ctx = EVP_MAC_CTX_new(mac); + if (*ctx == NULL) + return -1; + EVP_MAC_free(mac); + params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0); + params[1] = OSSL_PARAM_construct_end(); + EVP_MAC_init(*ctx, key, key_len, params); +#else *ctx = HMAC_CTX_new(); if (*ctx == NULL) return -1; HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); +#endif return 0; } @@ -241,22 +254,38 @@ static void __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, size_t data_len) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_update(*ctx, data, data_len); +#else HMAC_Update(*ctx, data, data_len); +#endif } static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + size_t len = *out_len; +#else unsigned int len = (unsigned int)*out_len; +#endif +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_final(*ctx, out, &len, *out_len); +#else HMAC_Final(*ctx, out, &len); +#endif *out_len = len; } static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_CTX_free(*ctx); +#else HMAC_CTX_free(*ctx); +#endif *ctx = NULL; } diff --git a/Utilities/cmlibarchive/libarchive/archive_hmac_private.h b/Utilities/cmlibarchive/libarchive/archive_hmac_private.h index 13a67d4955..50044a045e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_hmac_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_hmac_private.h @@ -74,9 +74,16 @@ typedef mbedtls_md_context_t archive_hmac_sha1_ctx; typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx; #elif defined(HAVE_LIBCRYPTO) +#include <openssl/opensslv.h> +#include <openssl/hmac.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +typedef EVP_MAC_CTX *archive_hmac_sha1_ctx; + +#else #include "archive_openssl_hmac_private.h" typedef HMAC_CTX* archive_hmac_sha1_ctx; +#endif #else diff --git a/Utilities/cmlibarchive/libarchive/archive_platform.h b/Utilities/cmlibarchive/libarchive/archive_platform.h index f87b423a54..63b255ee9d 100644 --- a/Utilities/cmlibarchive/libarchive/archive_platform.h +++ b/Utilities/cmlibarchive/libarchive/archive_platform.h @@ -188,8 +188,9 @@ /* * glibc 2.24 deprecates readdir_r + * bionic c deprecates readdir_r too */ -#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) +#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) && (!defined(__ANDROID__)) #define USE_READDIR_R 1 #else #undef USE_READDIR_R diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c index d0e1f35c82..5a94ec5d43 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c @@ -34,9 +34,6 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_SYS_PARAM_H #include <sys/param.h> #endif -#ifdef HAVE_SYS_MOUNT_H -#include <sys/mount.h> -#endif #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif @@ -54,6 +51,8 @@ __FBSDID("$FreeBSD$"); #endif #ifdef HAVE_LINUX_FS_H #include <linux/fs.h> +#elif HAVE_SYS_MOUNT_H +#include <sys/mount.h> #endif /* * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. @@ -109,6 +108,11 @@ __FBSDID("$FreeBSD$"); #define O_CLOEXEC 0 #endif +#if defined(__hpux) && !defined(HAVE_DIRFD) +#define dirfd(x) ((x)->__dd_fd) +#define HAVE_DIRFD +#endif + /*- * This is a new directory-walking system that addresses a number * of problems I've had with fts(3). In particular, it has no @@ -2098,6 +2102,8 @@ tree_push(struct tree *t, const char *path, int filesystem_id, struct tree_entry *te; te = calloc(1, sizeof(*te)); + if (te == NULL) + __archive_errx(1, "Out of memory"); te->next = t->stack; te->parent = t->current; if (te->parent) @@ -2428,7 +2434,7 @@ tree_dir_next_posix(struct tree *t) #else /* HAVE_FDOPENDIR */ if (tree_enter_working_dir(t) == 0) { t->d = opendir("."); -#if HAVE_DIRFD || defined(dirfd) +#ifdef HAVE_DIRFD __archive_ensure_cloexec_flag(dirfd(t->d)); #endif } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c index ea32e2aac0..f9d139557e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c @@ -418,8 +418,9 @@ la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype) FILE_FLAG_OPEN_REPARSE_POINT; int ret; - h = CreateFileW(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, flag, - NULL); + h = CreateFileW(path, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, flag, NULL); if (h == INVALID_HANDLE_VALUE) { la_dosmaperr(GetLastError()); return (-1); @@ -1073,7 +1074,9 @@ next_entry(struct archive_read_disk *a, struct tree *t, else flags |= FILE_FLAG_SEQUENTIAL_SCAN; t->entry_fh = CreateFileW(tree_current_access_path(t), - GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL); + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, flags, NULL); if (t->entry_fh == INVALID_HANDLE_VALUE) { la_dosmaperr(GetLastError()); archive_set_error(&a->archive, errno, @@ -2046,7 +2049,8 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st, if (sim_lstat && tree_current_is_physical_link(t)) flag |= FILE_FLAG_OPEN_REPARSE_POINT; - h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL, + h = CreateFileW(tree_current_access_path(t), 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flag, NULL); if (h == INVALID_HANDLE_VALUE) { la_dosmaperr(GetLastError()); @@ -2275,7 +2279,8 @@ archive_read_disk_entry_from_file(struct archive *_a, } else desiredAccess = GENERIC_READ; - h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL, + h = CreateFileW(path, desiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flag, NULL); if (h == INVALID_HANDLE_VALUE) { la_dosmaperr(GetLastError()); @@ -2337,7 +2342,8 @@ archive_read_disk_entry_from_file(struct archive *_a, if (fd >= 0) { h = (HANDLE)_get_osfhandle(fd); } else { - h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, + h = CreateFileW(path, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { la_dosmaperr(GetLastError()); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c index ae0b08003f..1e99542d7b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c @@ -450,7 +450,9 @@ lz4_filter_read_descriptor(struct archive_read_filter *self) chsum = (chsum >> 8) & 0xff; chsum_verifier = read_buf[descriptor_bytes-1] & 0xff; if (chsum != chsum_verifier) +#ifndef DONT_FAIL_ON_CRC_ERROR goto malformed_error; +#endif __archive_read_filter_consume(self->upstream, descriptor_bytes); @@ -521,7 +523,9 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) unsigned int chsum_block = archive_le32dec(read_buf + 4 + compressed_size); if (chsum != chsum_block) +#ifndef DONT_FAIL_ON_CRC_ERROR goto malformed_error; +#endif } @@ -652,10 +656,12 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) state->xxh32_state); state->xxh32_state = NULL; if (checksum != checksum_stream) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "lz4 stream checksum error"); return (ARCHIVE_FATAL); +#endif } } else if (ret > 0) __archive_xxhash.XXH32_update(state->xxh32_state, diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c index 42e2636dfc..cc1572f9d0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c @@ -283,7 +283,9 @@ consume_header(struct archive_read_filter *self) else checksum = adler32(adler32(0, NULL, 0), p, len); if (archive_be32dec(p + len) != checksum) +#ifndef DONT_FAIL_ON_CRC_ERROR goto corrupted; +#endif __archive_read_filter_consume(self->upstream, len + 4); if (flags & EXTRA_FIELD) { /* Skip extra field */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c index b978eb034e..90b0da2338 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c @@ -612,9 +612,11 @@ lzip_tail(struct archive_read_filter *self) /* Check the crc32 value of the uncompressed data of the current * member */ if (state->crc32 != archive_le32dec(f)) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Lzip: CRC32 error"); return (ARCHIVE_FAILED); +#endif } /* Check the uncompressed size of the current member */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c index 7d7e70243f..722edf1dbf 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c @@ -287,6 +287,7 @@ struct _7zip { const unsigned char *next_in; int64_t avail_in; int64_t total_in; + int64_t stream_in; unsigned char *next_out; int64_t avail_out; int64_t total_out; @@ -775,7 +776,7 @@ archive_read_format_7zip_read_header(struct archive_read *a, } /* Set up a more descriptive format name. */ - sprintf(zip->format_name, "7-Zip"); + snprintf(zip->format_name, sizeof(zip->format_name), "7-Zip"); a->archive.archive_format_name = zip->format_name; return (ret); @@ -986,15 +987,30 @@ ppmd_read(void *p) struct _7zip *zip = (struct _7zip *)(a->format->data); Byte b; - if (zip->ppstream.avail_in == 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated RAR file data"); - zip->ppstream.overconsumed = 1; - return (0); + if (zip->ppstream.avail_in <= 0) { + /* + * Ppmd7_DecodeSymbol might require reading multiple bytes + * and we are on boundary; + * last resort to read using __archive_read_ahead. + */ + ssize_t bytes_avail = 0; + const uint8_t* data = __archive_read_ahead(a, + zip->ppstream.stream_in+1, &bytes_avail); + if(bytes_avail < zip->ppstream.stream_in+1) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7z file data"); + zip->ppstream.overconsumed = 1; + return (0); + } + zip->ppstream.next_in++; + b = data[zip->ppstream.stream_in]; + } else { + b = *zip->ppstream.next_in++; } - b = *zip->ppstream.next_in++; zip->ppstream.avail_in--; zip->ppstream.total_in++; + zip->ppstream.stream_in++; return (b); } @@ -1485,6 +1501,7 @@ decompress(struct archive_read *a, struct _7zip *zip, } zip->ppstream.next_in = t_next_in; zip->ppstream.avail_in = t_avail_in; + zip->ppstream.stream_in = 0; zip->ppstream.next_out = t_next_out; zip->ppstream.avail_out = t_avail_out; if (zip->ppmd7_stat == 0) { @@ -2840,8 +2857,10 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, /* CRC check. */ if (crc32(0, (const unsigned char *)p + 12, 20) != archive_le32dec(p + 8)) { +#ifdef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, -1, "Header CRC error"); return (ARCHIVE_FATAL); +#endif } next_header_offset = archive_le64dec(p + 12); @@ -2891,8 +2910,10 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, /* Check the EncodedHeader CRC.*/ if (r == 0 && zip->header_crc32 != next_header_crc) { archive_set_error(&a->archive, -1, +#ifndef DONT_FAIL_ON_CRC_ERROR "Damaged 7-Zip archive"); r = -1; +#endif } if (r == 0) { if (zip->si.ci.folders[0].digest_defined) @@ -2943,9 +2964,11 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, /* Check the Header CRC.*/ if (check_header_crc && zip->header_crc32 != next_header_crc) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); return (ARCHIVE_FATAL); +#endif } break; default: diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c index 874237844f..6fcfbfcd30 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c @@ -996,7 +996,7 @@ archive_read_format_cab_read_header(struct archive_read *a, cab->end_of_entry_cleanup = cab->end_of_entry = 1; /* Set up a more descriptive format name. */ - sprintf(cab->format_name, "CAB %d.%d (%s)", + snprintf(cab->format_name, sizeof(cab->format_name), "CAB %d.%d (%s)", hd->major, hd->minor, cab->entry_cffolder->compname); a->archive.archive_format_name = cab->format_name; @@ -1134,7 +1134,7 @@ cab_checksum_update(struct archive_read *a, size_t bytes) } if (sumbytes) { int odd = sumbytes & 3; - if (sumbytes - odd > 0) + if ((int)(sumbytes - odd) > 0) cfdata->sum_calculated = cab_checksum_cfdata_4( p, sumbytes - odd, cfdata->sum_calculated); if (odd) @@ -1171,12 +1171,14 @@ cab_checksum_finish(struct archive_read *a) cfdata->sum_calculated = cab_checksum_cfdata( cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); if (cfdata->sum_calculated != cfdata->sum) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes", cab->entry_cffolder->cfdata_index -1, cfdata->sum, cfdata->sum_calculated, cfdata->compressed_size); return (ARCHIVE_FAILED); +#endif } return (ARCHIVE_OK); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c index 912116675f..380cbb8b42 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c @@ -1007,7 +1007,8 @@ read_children(struct archive_read *a, struct file_info *parent) p = b; b += iso9660->logical_block_size; step -= iso9660->logical_block_size; - for (; *p != 0 && p < b && p + *p <= b; p += *p) { + for (; *p != 0 && p + DR_name_offset < b && p + *p <= b; + p += *p) { struct file_info *child; /* N.B.: these special directory identifiers @@ -1756,7 +1757,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, size_t name_len; const unsigned char *rr_start, *rr_end; const unsigned char *p; - size_t dr_len; + size_t dr_len = 0; uint64_t fsize, offset; int32_t location; int flags; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c index 1357f9aabf..8b7bf663ba 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c @@ -739,7 +739,7 @@ archive_read_format_lha_read_header(struct archive_read *a, if (lha->directory || lha->compsize == 0) lha->end_of_entry = 1; - sprintf(lha->format_name, "lha -%c%c%c-", + snprintf(lha->format_name, sizeof(lha->format_name), "lha -%c%c%c-", lha->method[0], lha->method[1], lha->method[2]); a->archive.archive_format_name = lha->format_name; @@ -1039,9 +1039,11 @@ lha_read_file_header_2(struct archive_read *a, struct lha *lha) } if (header_crc != lha->header_crc) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "LHa header CRC error"); return (ARCHIVE_FATAL); +#endif } return (err); } @@ -1107,9 +1109,11 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha) return (err); if (header_crc != lha->header_crc) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "LHa header CRC error"); return (ARCHIVE_FATAL); +#endif } return (err); invalid: diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c index 88bca76fb9..2bc3ba066c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c @@ -692,7 +692,7 @@ detect_form(struct archive_read *a, int *is_form_d) { const char *p; ssize_t avail, ravail; - ssize_t detected_bytes = 0, len, nl; + ssize_t len, nl; int entry_cnt = 0, multiline = 0; int form_D = 0;/* The archive is generated by `NetBSD mtree -D' * (In this source we call it `form D') . */ @@ -728,8 +728,6 @@ detect_form(struct archive_read *a, int *is_form_d) * character of previous line was '\' character. */ if (bid_keyword_list(p, len, 0, 0) <= 0) break; - if (multiline == 1) - detected_bytes += len; if (p[len-nl-1] != '\\') { if (multiline == 1 && ++entry_cnt >= MAX_BID_ENTRY) @@ -745,7 +743,6 @@ detect_form(struct archive_read *a, int *is_form_d) keywords = bid_entry(p, len, nl, &last_is_path); if (keywords >= 0) { - detected_bytes += len; if (form_D == 0) { if (last_is_path) form_D = 1; @@ -997,9 +994,11 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, struct mtree_entry *alt; alt = (struct mtree_entry *)__archive_rb_tree_find_node( &mtree->rbtree, entry->name); - while (alt->next_dup) - alt = alt->next_dup; - alt->next_dup = entry; + if (alt != NULL) { + while (alt->next_dup) + alt = alt->next_dup; + alt->next_dup = entry; + } } } @@ -1074,7 +1073,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree) continue; /* Non-printable characters are not allowed */ for (s = p;s < p + len - 1; s++) { - if (!isprint((unsigned char)*s)) { + if (!isprint((unsigned char)*s) && *s != '\t') { r = ARCHIVE_FATAL; break; } @@ -1253,9 +1252,17 @@ parse_file(struct archive_read *a, struct archive_entry *entry, archive_entry_filetype(entry) == AE_IFDIR) { mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(mtree->fd); - if (mtree->fd == -1 && - (errno != ENOENT || - archive_strlen(&mtree->contents_name) > 0)) { + if (mtree->fd == -1 && ( +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * On Windows, attempting to open a file with an + * invalid name result in EINVAL (Error 22) + */ + (errno != ENOENT && errno != EINVAL) +#else + errno != ENOENT +#endif + || archive_strlen(&mtree->contents_name) > 0)) { archive_set_error(&a->archive, errno, "Can't open %s", path); r = ARCHIVE_WARN; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c index 5c02a25cbb..1c9a057b60 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c @@ -430,7 +430,7 @@ static int new_node(struct huffman_code *); static int make_table(struct archive_read *, struct huffman_code *); static int make_table_recurse(struct archive_read *, struct huffman_code *, int, struct huffman_table_entry *, int, int); -static int64_t expand(struct archive_read *, int64_t); +static int expand(struct archive_read *, int64_t *); static int copy_from_lzss_window_to_unp(struct archive_read *, const void **, int64_t, int); static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *); @@ -1007,9 +1007,11 @@ archive_read_format_rar_read_header(struct archive_read *a, crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2); if ((crc32_val & 0xffff) != archive_le16dec(p)) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Header CRC error"); return (ARCHIVE_FATAL); +#endif } __archive_read_consume(a, skip); break; @@ -1065,9 +1067,11 @@ archive_read_format_rar_read_header(struct archive_read *a, skip -= to_read; } if ((crc32_val & 0xffff) != crc32_expected) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Header CRC error"); return (ARCHIVE_FATAL); +#endif } if (head_type == ENDARC_HEAD) return (ARCHIVE_EOF); @@ -1432,9 +1436,11 @@ read_header(struct archive_read *a, struct archive_entry *entry, /* File Header CRC check. */ crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7)); if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Header CRC error"); return (ARCHIVE_FATAL); +#endif } /* If no CRC error, Go on parsing File Header. */ p = h; @@ -1952,9 +1958,11 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, *size = 0; *offset = rar->offset; if (rar->file_crc != rar->crc_calculated) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "File CRC error"); return (ARCHIVE_FATAL); +#endif } rar->entry_eof = 1; return (ARCHIVE_EOF); @@ -1988,7 +1996,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, return (ARCHIVE_FATAL); struct rar *rar; - int64_t start, end, actualend; + int64_t start, end; size_t bs; int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i; @@ -2045,9 +2053,11 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, *size = 0; *offset = rar->offset; if (rar->file_crc != rar->crc_calculated) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "File CRC error"); return (ARCHIVE_FATAL); +#endif } rar->entry_eof = 1; return (ARCHIVE_EOF); @@ -2179,11 +2189,12 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, end = rar->filters.filterstart; } - if ((actualend = expand(a, end)) < 0) - return ((int)actualend); + ret = expand(a, &end); + if (ret != ARCHIVE_OK) + return (ret); - rar->bytes_uncopied = actualend - start; - rar->filters.lastend = actualend; + rar->bytes_uncopied = end - start; + rar->filters.lastend = end; if (rar->filters.lastend != rar->filters.filterstart && rar->bytes_uncopied == 0) { /* Broken RAR files cause this case. * NOTE: If this case were possible on a normal RAR file @@ -2825,8 +2836,8 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, return ret; } -static int64_t -expand(struct archive_read *a, int64_t end) +static int +expand(struct archive_read *a, int64_t *end) { static const unsigned char lengthbases[] = { 0, 1, 2, 3, 4, 5, 6, @@ -2873,16 +2884,19 @@ expand(struct archive_read *a, int64_t end) struct rar *rar = (struct rar *)(a->format->data); struct rar_br *br = &(rar->br); - if (rar->filters.filterstart < end) - end = rar->filters.filterstart; + if (rar->filters.filterstart < *end) + *end = rar->filters.filterstart; while (1) { - if(lzss_position(&rar->lzss) >= end) - return end; + if(lzss_position(&rar->lzss) >= *end) { + return (ARCHIVE_OK); + } - if(rar->is_ppmd_block) - return lzss_position(&rar->lzss); + if(rar->is_ppmd_block) { + *end = lzss_position(&rar->lzss); + return (ARCHIVE_OK); + } if ((symbol = read_next_symbol(a, &rar->maincode)) < 0) return (ARCHIVE_FATAL); @@ -2906,7 +2920,8 @@ expand(struct archive_read *a, int64_t end) goto truncated_data; rar->start_new_table = rar_br_bits(br, 1); rar_br_consume(br, 1); - return lzss_position(&rar->lzss); + *end = lzss_position(&rar->lzss); + return (ARCHIVE_OK); } else { @@ -2917,7 +2932,7 @@ expand(struct archive_read *a, int64_t end) } else if(symbol==257) { - if (!read_filter(a, &end)) + if (!read_filter(a, end)) return (ARCHIVE_FATAL); continue; } @@ -3323,14 +3338,43 @@ run_filters(struct archive_read *a) struct rar *rar = (struct rar *)(a->format->data); struct rar_filters *filters = &rar->filters; struct rar_filter *filter = filters->stack; - size_t start = filters->filterstart; - size_t end = start + filter->blocklength; + struct rar_filter *f; + size_t start, end; + int64_t tend; uint32_t lastfilteraddress; uint32_t lastfilterlength; int ret; + if (filters == NULL || filter == NULL) + return (0); + + start = filters->filterstart; + end = start + filter->blocklength; + filters->filterstart = INT64_MAX; - end = (size_t)expand(a, end); + tend = (int64_t)end; + ret = expand(a, &tend); + if (ret != ARCHIVE_OK) + return 0; + + /* Check if filter stack was modified in expand() */ + ret = ARCHIVE_FATAL; + f = filters->stack; + while (f) + { + if (f == filter) + { + ret = ARCHIVE_OK; + break; + } + f = f->next; + } + if (ret != ARCHIVE_OK) + return 0; + + if (tend < 0) + return 0; + end = (size_t)tend; if (end != start + filter->blocklength) return 0; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c index 8850c93e9e..548da4e6a9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c @@ -2821,11 +2821,13 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p, ^ (uint8_t) (*block_size >> 16); if(calculated_cksum != hdr->block_cksum) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Block checksum error: got 0x%x, expected 0x%x", hdr->block_cksum, calculated_cksum); return ARCHIVE_FATAL; +#endif } return ARCHIVE_OK; @@ -3911,6 +3913,13 @@ static int do_unpack(struct archive_read* a, struct rar5* rar, case GOOD: /* fallthrough */ case BEST: + /* No data is returned here. But because a sparse-file aware + * caller (like archive_read_data_into_fd) may treat zero-size + * as a sparse file block, we need to update the offset + * accordingly. At this point the decoder doesn't have any + * pending uncompressed data blocks, so the current position in + * the output file should be last_write_ptr. */ + if (offset) *offset = rar->cstate.last_write_ptr; return uncompress_file(a); default: archive_set_error(&a->archive, diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c index bfdad7f873..93c3fd5857 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c @@ -407,14 +407,13 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid) /* * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields. */ - if (bid > 0 && ( - validate_number_field(header->mode, sizeof(header->mode)) == 0 + if (validate_number_field(header->mode, sizeof(header->mode)) == 0 || validate_number_field(header->uid, sizeof(header->uid)) == 0 || validate_number_field(header->gid, sizeof(header->gid)) == 0 || validate_number_field(header->mtime, sizeof(header->mtime)) == 0 || validate_number_field(header->size, sizeof(header->size)) == 0 || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0 - || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) { + || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0) { bid = 0; } @@ -2108,6 +2107,21 @@ pax_attribute(struct archive_read *a, struct tar *tar, /* "size" is the size of the data in the entry. */ tar->entry_bytes_remaining = tar_atol10(value, strlen(value)); + if (tar->entry_bytes_remaining < 0) { + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Tar size attribute is negative"); + return (ARCHIVE_FATAL); + } + if (tar->entry_bytes_remaining == INT64_MAX) { + /* Note: tar_atol returns INT64_MAX on overflow */ + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Tar size attribute overflow"); + return (ARCHIVE_FATAL); + } /* * The "size" pax header keyword always overrides the * "size" field in the tar header. diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c index 2e60cf7213..330df5879a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c @@ -624,7 +624,9 @@ read_toc(struct archive_read *a) __archive_read_consume(a, xar->toc_chksum_size); xar->offset += xar->toc_chksum_size; if (r != ARCHIVE_OK) +#ifndef DONT_FAIL_ON_CRC_ERROR return (ARCHIVE_FATAL); +#endif } /* @@ -827,10 +829,12 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) xattr->a_sum.val, xattr->a_sum.len, xattr->e_sum.val, xattr->e_sum.len); if (r != ARCHIVE_OK) { +#ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "Xattr checksum error"); r = ARCHIVE_WARN; break; +#endif } if (xattr->name.s == NULL) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index 8ad73b6cc5..e126ae38fa 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@ -1667,7 +1667,7 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) */ /* Read magic1,magic2,lzma_params from the ZIPX stream. */ - if((p = __archive_read_ahead(a, 9, NULL)) == NULL) { + if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzma data"); return (ARCHIVE_FATAL); diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c index d7f2c46b28..69458e1a12 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string.c +++ b/Utilities/cmlibarchive/libarchive/archive_string.c @@ -3988,10 +3988,10 @@ int archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes, const char **p, size_t *length, struct archive_string_conv *sc) { - int r, ret = 0; - - (void)r; /* UNUSED */ + int ret = 0; #if defined(_WIN32) && !defined(__CYGWIN__) + int r; + /* * Internationalization programming on Windows must use Wide * characters because Windows platform cannot make locale UTF-8. diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c index 66592e8268..27626b5414 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write.c +++ b/Utilities/cmlibarchive/libarchive/archive_write.c @@ -201,6 +201,10 @@ __archive_write_allocate_filter(struct archive *_a) struct archive_write_filter *f; f = calloc(1, sizeof(*f)); + + if (f == NULL) + return (NULL); + f->archive = _a; f->state = ARCHIVE_WRITE_FILTER_STATE_NEW; if (a->filter_first == NULL) @@ -548,6 +552,10 @@ archive_write_open2(struct archive *_a, void *client_data, a->client_data = client_data; client_filter = __archive_write_allocate_filter(_a); + + if (client_filter == NULL) + return (ARCHIVE_FATAL); + client_filter->open = archive_write_client_open; client_filter->write = archive_write_client_write; client_filter->close = archive_write_client_close; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c index b6d3d0ae01..bd5180e763 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c @@ -1996,6 +1996,8 @@ archive_write_disk_new(void) free(a); return (NULL); } + a->path_safe.s[0] = 0; + #ifdef HAVE_ZLIB_H a->decmpfs_compression_level = 5; #endif @@ -2793,7 +2795,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, char *tail; char *head; int last; - char c; + char c = '\0'; int r; struct stat st; int chdir_fd; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c index 1b12a299ca..88df3ce020 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c @@ -1370,6 +1370,7 @@ archive_write_disk_new(void) free(a); return (NULL); } + a->path_safe.s[0] = 0; return (&a->archive); } @@ -2154,6 +2155,8 @@ check_symlinks(struct archive_write_disk *a) return (ARCHIVE_FAILED); } } + if (!c) + break; pn[0] = c; pn++; } @@ -2258,6 +2261,9 @@ cleanup_pathname(struct archive_write_disk *a, wchar_t *name) return (ARCHIVE_FAILED); } else p += 4; + /* Network drive path like "\\<server-name>\<share-name>\file" */ + } else if (p[0] == L'\\' && p[1] == L'\\') { + p += 2; } /* Skip leading drive letter from archives created diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3 index 29bffe49eb..6bceb964f5 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_open.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3 @@ -218,6 +218,7 @@ On failure, the callback should invoke .Fn archive_set_error to register an error code and message and return +.Cm ARCHIVE_FATAL . .Bl -item -offset indent .It .Ft typedef int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c index 52911491f6..cf1f4770eb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c @@ -1717,7 +1717,7 @@ build_pax_attribute_name(char *dest, const char *src) * to having clients override it. */ #if HAVE_GETPID && 0 /* Disable this for now; see above comment. */ - sprintf(buff, "PaxHeader.%d", getpid()); + snprintf(buff, sizeof(buff), "PaxHeader.%d", getpid()); #else /* If the platform can't fetch the pid, don't include it. */ strcpy(buff, "PaxHeader"); diff --git a/Utilities/cmlibarchive/libarchive/cpio.5 b/Utilities/cmlibarchive/libarchive/cpio.5 index 837a45692e..c71018b199 100644 --- a/Utilities/cmlibarchive/libarchive/cpio.5 +++ b/Utilities/cmlibarchive/libarchive/cpio.5 @@ -354,7 +354,7 @@ while working in AT&T's Unix Support Group. It appeared in 1977 as part of PWB/UNIX 1.0, the .Dq Programmer's Work Bench derived from -.At 6th Edition UNIX +.At v6 that was used internally at AT&T. Both the new binary and old character formats were in use by 1980, according to the System III source released diff --git a/Utilities/cmlibarchive/libarchive/filter_fork_posix.c b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c index ac255c4f8b..62085a7099 100644 --- a/Utilities/cmlibarchive/libarchive/filter_fork_posix.c +++ b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c @@ -76,7 +76,7 @@ int __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, pid_t *out_child) { - pid_t child; + pid_t child = -1; int stdin_pipe[2], stdout_pipe[2], tmp; #if HAVE_POSIX_SPAWNP posix_spawn_file_actions_t actions; |