Merge branch 'release-4.3'
diff --git a/.clang-format b/.clang-format
index 84b96ab..a733a1a 100644
--- a/.clang-format
+++ b/.clang-format
@@ -33,6 +33,8 @@
Priority: 3
- Regex: '^<sys/'
Priority: 5
+ - Regex: '^"QCMake'
+ Priority: 11
- Regex: '^(<|")Qt?[A-Z]'
Priority: 6
- Regex: '^<cmtp/'
diff --git a/.clang-tidy b/.clang-tidy
index f83585a..ccd74be 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -33,6 +33,7 @@
-modernize-macro-to-enum,\
-modernize-return-braced-init-list,\
-modernize-type-traits,\
+-modernize-unary-static-assert, \
-modernize-use-emplace,\
-modernize-use-nodiscard,\
-modernize-use-noexcept,\
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 289c6c6..fd56c98 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -388,6 +388,16 @@
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
+t:fedora43-ninja-gcc-std-reloc:
+ extends:
+ - .fedora43_ninja_gcc_std_reloc
+ - .cmake_test_linux_release
+ - .linux_x86_64_tags
+ - .rules
+ - .needs_centos7_x86_64
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
t:fedora43-ninja-multi-clang:
extends:
- .fedora43_ninja_multi_clang
@@ -450,11 +460,11 @@
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:nvhpc24.9-ninja:
+t:nvhpc26.3-ninja:
extends:
- .nvhpc_ninja
- .cmake_test_linux_release
- - .linux_x86_64_v3_tags_cuda_arch_52
+ - .linux_x86_64_v3_tags_cuda_arch_75
- .rules
- .needs_centos7_x86_64
variables:
@@ -637,36 +647,6 @@
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:linux-gcc-cxx-modules-reloc-ninja:
- extends:
- - .gcc_cxx_modules_reloc_ninja
- - .cmake_test_linux_release
- - .linux_x86_64_tags
- - .rules
- - .needs_centos7_x86_64
- variables:
- CMAKE_CI_JOB_NIGHTLY: "true"
-
-t:linux-gcc-cxx-modules-ninja:
- extends:
- - .gcc_cxx_modules_ninja
- - .cmake_test_linux_release
- - .linux_x86_64_tags
- - .rules
- - .needs_centos7_x86_64
- variables:
- CMAKE_CI_JOB_NIGHTLY: "true"
-
-t:linux-gcc-cxx-modules-ninja-multi:
- extends:
- - .gcc_cxx_modules_ninja_multi
- - .cmake_test_linux_release
- - .linux_x86_64_tags
- - .rules
- - .needs_centos7_x86_64
- variables:
- CMAKE_CI_JOB_NIGHTLY: "true"
-
t:debian10-legacy:
extends:
- .debian10_legacy
@@ -799,34 +779,6 @@
CMAKE_CI_BUILD_NAME: intel2020u4_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u4-el8
-t:intel2021.1.1-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: intel2021.1.1_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.1-el8
-
-t:intel2021.1.2-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: intel2021.1.2_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8
-
-t:intel2021.2.0-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: intel2021.2.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.2.0-el8
-
-t:intel2021.3.0-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: intel2021.3.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.3.0-el8
-
t:intel2021.4.0-makefiles:
extends:
- .cmake_test_linux_intelclassic_makefiles
@@ -834,20 +786,6 @@
CMAKE_CI_BUILD_NAME: intel2021.4.0_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.4.0-el8
-t:intel2021.5.0-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: intel2021.5.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.0.2-el8
-
-t:intel2021.6.0-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: intel2021.6.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.1.0-el8
-
t:intel2021.7.0-makefiles:
extends:
- .cmake_test_linux_intelclassic_makefiles
@@ -855,20 +793,6 @@
CMAKE_CI_BUILD_NAME: intel2021.7.0_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.2.0-el8
-t:intel2021.8.0-makefiles:
- extends:
- - .cmake_test_linux_intelclassic_makefiles
- variables:
- 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:intel2021.10.0-makefiles:
extends:
- .cmake_test_linux_intelclassic_makefiles
@@ -876,34 +800,6 @@
CMAKE_CI_BUILD_NAME: intel2021.10.0_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2023.2.1-el8
-t:oneapi2021.1.1-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2021.1.1_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.1-el8
-
-t:oneapi2021.1.2-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2021.1.2_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8
-
-t:oneapi2021.2.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2021.2.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.2.0-el8
-
-t:oneapi2021.3.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2021.3.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.3.0-el8
-
t:oneapi2021.4.0-makefiles:
extends:
- .cmake_test_linux_inteloneapi_makefiles
@@ -911,20 +807,6 @@
CMAKE_CI_BUILD_NAME: oneapi2021.4.0_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.4.0-el8
-t:oneapi2022.0.2-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2022.0.2_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.0.2-el8
-
-t:oneapi2022.1.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2022.1.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.1.0-el8
-
t:oneapi2022.2.0-makefiles:
extends:
- .cmake_test_linux_inteloneapi_makefiles
@@ -932,20 +814,6 @@
CMAKE_CI_BUILD_NAME: oneapi2022.2.0_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.2.0-el8
-t:oneapi2023.0.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- 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
-
t:oneapi2023.2.0-makefiles:
extends:
- .cmake_test_linux_inteloneapi_makefiles
@@ -953,20 +821,6 @@
CMAKE_CI_BUILD_NAME: oneapi2023.2.1_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2023.2.1-el8
-t:oneapi2024.0.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2024.0.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2024.0.0-el8
-
-t:oneapi2024.1.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2024.1.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2024.1.0-el8
-
t:oneapi2024.2.0-makefiles:
extends:
- .cmake_test_linux_inteloneapi_makefiles
@@ -974,27 +828,6 @@
CMAKE_CI_BUILD_NAME: oneapi2024.2.0_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2024.2.0-rocky9
-t:oneapi2025.0.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2025.0.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2025.0.0-rocky9
-
-t:oneapi2025.1.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2025.1.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2025.1.0-rocky9
-
-t:oneapi2025.2.0-makefiles:
- extends:
- - .cmake_test_linux_inteloneapi_makefiles
- variables:
- CMAKE_CI_BUILD_NAME: oneapi2025.2.0_makefiles
- CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2025.2.0-rocky9
-
t:oneapi2025.3.0-makefiles:
extends:
- .cmake_test_linux_inteloneapi_makefiles
@@ -1554,7 +1387,20 @@
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:windows-clang21.1-cl-ninja:
+t:windows-clang22.1-cl-fastbuild:
+ extends:
+ - .windows_clang_fastbuild
+ - .cmake_test_windows_external
+ - .windows_x86_64_tags_concurrent_vs2022_msvc14.44
+ - .cmake_junit_artifacts
+ - .rules
+ needs:
+ - t:windows-vs2026-x64-ninja
+ variables:
+ CMAKE_CI_BUILD_NAME: windows_clang22.1_cl_fastbuild
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
+t:windows-clang22.1-cl-ninja:
extends:
- .windows_clang_ninja
- .cmake_test_windows_external
@@ -1564,10 +1410,10 @@
needs:
- t:windows-vs2026-x64-ninja
variables:
- CMAKE_CI_BUILD_NAME: windows_clang21.1_cl_ninja
+ CMAKE_CI_BUILD_NAME: windows_clang22.1_cl_ninja
CMAKE_CI_JOB_NIGHTLY: "true"
-t:windows-clang21.1-cl-nmake:
+t:windows-clang22.1-cl-nmake:
extends:
- .windows_clang_nmake
- .cmake_test_windows_external
@@ -1577,10 +1423,10 @@
needs:
- t:windows-vs2026-x64-ninja
variables:
- CMAKE_CI_BUILD_NAME: windows_clang21.1_cl_nmake
+ CMAKE_CI_BUILD_NAME: windows_clang22.1_cl_nmake
CMAKE_CI_JOB_NIGHTLY: "true"
-t:windows-clang21.1-gnu-ninja:
+t:windows-clang22.1-gnu-ninja:
extends:
- .windows_clang_ninja
- .cmake_test_windows_external
@@ -1590,10 +1436,10 @@
needs:
- t:windows-vs2026-x64-ninja
variables:
- CMAKE_CI_BUILD_NAME: windows_clang21.1_gnu_ninja
+ CMAKE_CI_BUILD_NAME: windows_clang22.1_gnu_ninja
CMAKE_CI_JOB_NIGHTLY: "true"
-t:windows-clang21.1-gnu-nmake:
+t:windows-clang22.1-gnu-nmake:
extends:
- .windows_clang_nmake
- .cmake_test_windows_external
@@ -1603,7 +1449,7 @@
needs:
- t:windows-vs2026-x64-ninja
variables:
- CMAKE_CI_BUILD_NAME: windows_clang21.1_gnu_nmake
+ CMAKE_CI_BUILD_NAME: windows_clang22.1_gnu_nmake
CMAKE_CI_JOB_NIGHTLY: "true"
t:windows-intel2021.9-ninja:
@@ -1680,9 +1526,33 @@
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:windows-orangec6.73.1:
+t:windows-orangec6.73.8:
extends:
- - .windows_orangec6.73.1
+ - .windows_orangec6.73.8
+ - .cmake_test_windows_external
+ - .windows_x86_64_tags_concurrent
+ - .cmake_junit_artifacts
+ - .rules
+ needs:
+ - t:windows-vs2026-x64-ninja
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
+t:windows-orangec7.0.7:
+ extends:
+ - .windows_orangec7.0.7
+ - .cmake_test_windows_external
+ - .windows_x86_64_tags_concurrent
+ - .cmake_junit_artifacts
+ - .rules
+ needs:
+ - t:windows-vs2026-x64-ninja
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
+t:windows-pellesc13.01:
+ extends:
+ - .windows_pellesc13.01
- .cmake_test_windows_external
- .windows_x86_64_tags_concurrent
- .cmake_junit_artifacts
diff --git a/.gitlab/.gitignore b/.gitlab/.gitignore
index 91e677b..4d33c62 100644
--- a/.gitlab/.gitignore
+++ b/.gitlab/.gitignore
@@ -19,6 +19,7 @@
/openmp
/open-watcom*
/orangec
+/pellesc
/python*
/qt*
/sccache*
diff --git a/.gitlab/ci/clang.ps1 b/.gitlab/ci/clang.ps1
index 327fe3b..20830cc 100644
--- a/.gitlab/ci/clang.ps1
+++ b/.gitlab/ci/clang.ps1
@@ -1,10 +1,10 @@
$erroractionpreference = "stop"
-if ("$env:CMAKE_CI_BUILD_NAME".Contains("clang21.1")) {
- # LLVM/Clang 21.1.8
- # https://github.com/llvm/llvm-project/releases/tag/llvmorg-21.1.8
- $filename = "llvm-21.1.8-win-x86_64-1"
- $sha256sum = "3DB0063A6E434C694799CDD70052F27F08A758F1FF4B4C04D9910AD4198F6064"
+if ("$env:CMAKE_CI_BUILD_NAME".Contains("clang22.1")) {
+ # LLVM/Clang 22.1.2
+ # https://github.com/llvm/llvm-project/releases/tag/llvmorg-22.1.2
+ $filename = "llvm-22.1.2-win-x86_64-1"
+ $sha256sum = "31022498417A1225FABF31EE66AF11971BA2E4BA97FFE7A10F9A206CAD8A85E7"
} else {
throw ('unknown CMAKE_CI_BUILD_NAME: ' + "$env:CMAKE_CI_BUILD_NAME")
}
diff --git a/.gitlab/ci/configure_debian13_aarch64_ninja.cmake b/.gitlab/ci/configure_debian13_aarch64_ninja.cmake
index 90fb7d9..c42b18d 100644
--- a/.gitlab/ci/configure_debian13_aarch64_ninja.cmake
+++ b/.gitlab/ci/configure_debian13_aarch64_ninja.cmake
@@ -106,6 +106,7 @@
set(CMake_TEST_IPO_WORKS_CXX "ON" CACHE BOOL "")
set(CMake_TEST_IPO_WORKS_Fortran "ON" CACHE BOOL "")
set(CMake_TEST_JQ "/usr/bin/jq" CACHE PATH "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_Qt5 "ON" CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
diff --git a/.gitlab/ci/configure_debian13_ninja_common.cmake b/.gitlab/ci/configure_debian13_ninja_common.cmake
index 8b1bf14..7cc4099 100644
--- a/.gitlab/ci/configure_debian13_ninja_common.cmake
+++ b/.gitlab/ci/configure_debian13_ninja_common.cmake
@@ -106,6 +106,7 @@
set(CMake_TEST_IPO_WORKS_CXX "ON" CACHE BOOL "")
set(CMake_TEST_IPO_WORKS_Fortran "ON" CACHE BOOL "")
set(CMake_TEST_JQ "/usr/bin/jq" CACHE PATH "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_Qt5 "ON" CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
diff --git a/.gitlab/ci/configure_fedora43_bullseye_coverage.cmake b/.gitlab/ci/configure_fedora43_bullseye_coverage.cmake
index 5b35c57..e9cf156 100644
--- a/.gitlab/ci/configure_fedora43_bullseye_coverage.cmake
+++ b/.gitlab/ci/configure_fedora43_bullseye_coverage.cmake
@@ -12,6 +12,7 @@
set(ENV{KWSYS_TEST_PROCESS_1_COUNT} 11)
set(CMake_TEST_GUI "ON" CACHE BOOL "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database,import_std23" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
diff --git a/.gitlab/ci/configure_fedora43_gcc_gcov.cmake b/.gitlab/ci/configure_fedora43_gcc_gcov.cmake
index b2eb3ac..22cbc33 100644
--- a/.gitlab/ci/configure_fedora43_gcc_gcov.cmake
+++ b/.gitlab/ci/configure_fedora43_gcc_gcov.cmake
@@ -1,4 +1,5 @@
set(CMake_TEST_GUI "ON" CACHE BOOL "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database,import_std23" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
diff --git a/.gitlab/ci/configure_fedora43_makefiles.cmake b/.gitlab/ci/configure_fedora43_makefiles.cmake
index 3ddf236..2cd93f4 100644
--- a/.gitlab/ci/configure_fedora43_makefiles.cmake
+++ b/.gitlab/ci/configure_fedora43_makefiles.cmake
@@ -109,6 +109,8 @@
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
set(CMake_TEST_LOCALE_CHARSET "ISO-8859-1" CACHE STRING "")
+set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_Qt5 "ON" CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
diff --git a/.gitlab/ci/configure_fedora43_ninja.cmake b/.gitlab/ci/configure_fedora43_ninja.cmake
index 0371ebc..6f4dbac 100644
--- a/.gitlab/ci/configure_fedora43_ninja.cmake
+++ b/.gitlab/ci/configure_fedora43_ninja.cmake
@@ -5,6 +5,8 @@
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
+set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database,import_std23" CACHE STRING "")
set(CMake_TEST_Rust "ON" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
diff --git a/.gitlab/ci/configure_fedora43_ninja_gcc_std_reloc.cmake b/.gitlab/ci/configure_fedora43_ninja_gcc_std_reloc.cmake
new file mode 100644
index 0000000..6cd5f3e
--- /dev/null
+++ b/.gitlab/ci/configure_fedora43_ninja_gcc_std_reloc.cmake
@@ -0,0 +1,4 @@
+set(CMake_TEST_CXX_STDLIB_MODULES_JSON "$ENV{CMAKE_CI_CXX_STDLIB_MODULES_JSON}" CACHE FILEPATH "")
+set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database,import_std23" CACHE STRING "")
+
+include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake
deleted file mode 100644
index b7faa36..0000000
--- a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,bmionly,build_database,import_std23" CACHE STRING "")
-
-include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake
deleted file mode 100644
index b7faa36..0000000
--- a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,bmionly,build_database,import_std23" CACHE STRING "")
-
-include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_reloc_ninja.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_reloc_ninja.cmake
deleted file mode 100644
index eb728ed..0000000
--- a/.gitlab/ci/configure_linux_gcc_cxx_modules_reloc_ninja.cmake
+++ /dev/null
@@ -1,13 +0,0 @@
-# "Misplace" the `libstdc++.modules.json` file so that
-# `CMAKE_CXX_STDLIB_MODULES_JSON` is needed to use `import std`.
-set(gcc_prefix "/opt/gcc-importstd")
-set(CMake_TEST_CXX_STDLIB_MODULES_JSON
- "${gcc_prefix}/lib64.reloc/libstdc++.modules.json"
- CACHE FILEPATH "")
-file(MAKE_DIRECTORY
- "${gcc_prefix}/lib64.reloc")
-file(RENAME
- "${gcc_prefix}/lib64/libstdc++.modules.json"
- "${CMake_TEST_CXX_STDLIB_MODULES_JSON}")
-
-include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/configure_macos_arm64_ninja.cmake b/.gitlab/ci/configure_macos_arm64_ninja.cmake
index c1924fe..1d0787c 100644
--- a/.gitlab/ci/configure_macos_arm64_ninja.cmake
+++ b/.gitlab/ci/configure_macos_arm64_ninja.cmake
@@ -7,6 +7,8 @@
set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "")
set(CMake_TEST_GUI "ON" CACHE BOOL "")
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
+set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERSION "1.2" CACHE STRING "")
diff --git a/.gitlab/ci/configure_macos_x86_64_makefiles.cmake b/.gitlab/ci/configure_macos_x86_64_makefiles.cmake
index 99beb68..1a5a6e5 100644
--- a/.gitlab/ci/configure_macos_x86_64_makefiles.cmake
+++ b/.gitlab/ci/configure_macos_x86_64_makefiles.cmake
@@ -6,6 +6,7 @@
if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERSION "1.2" CACHE STRING "")
diff --git a/.gitlab/ci/configure_macos_x86_64_ninja.cmake b/.gitlab/ci/configure_macos_x86_64_ninja.cmake
index 1af144f..c3c3d83 100644
--- a/.gitlab/ci/configure_macos_x86_64_ninja.cmake
+++ b/.gitlab/ci/configure_macos_x86_64_ninja.cmake
@@ -10,6 +10,8 @@
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
+set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
+set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERSION "1.2" CACHE STRING "")
diff --git a/.gitlab/ci/configure_nvhpc_ninja.cmake b/.gitlab/ci/configure_nvhpc_ninja.cmake
index e25ff72..b72c4aa 100644
--- a/.gitlab/ci/configure_nvhpc_ninja.cmake
+++ b/.gitlab/ci/configure_nvhpc_ninja.cmake
@@ -1,9 +1,9 @@
set(CMake_TEST_CUDA "NVIDIA" CACHE STRING "")
-set(CMake_TEST_CUDA_ARCH "52" CACHE STRING "")
+set(CMake_TEST_CUDA_ARCH "75" CACHE STRING "")
set(CMake_TEST_CUDA_CUPTI "ON" CACHE STRING "")
-set(CMake_TEST_C_STANDARDS "90;99;11;17" CACHE STRING "")
-set(CMake_TEST_CXX_STANDARDS "98;11;14;17;20;23" CACHE STRING "")
+set(CMake_TEST_C_STANDARDS "90;99;11;17;23" CACHE STRING "")
+set(CMake_TEST_CXX_STANDARDS "98;11;14;17;20;23;26" CACHE STRING "")
set(configure_no_sccache 1)
diff --git a/.gitlab/ci/configure_windows_clang_fastbuild.cmake b/.gitlab/ci/configure_windows_clang_fastbuild.cmake
new file mode 100644
index 0000000..ba19834
--- /dev/null
+++ b/.gitlab/ci/configure_windows_clang_fastbuild.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_clang_common.cmake")
diff --git a/.gitlab/ci/configure_windows_clang_ninja.cmake b/.gitlab/ci/configure_windows_clang_ninja.cmake
index 214c754..e8a0171 100644
--- a/.gitlab/ci/configure_windows_clang_ninja.cmake
+++ b/.gitlab/ci/configure_windows_clang_ninja.cmake
@@ -1,4 +1,2 @@
-if("$ENV{CMAKE_CI_BUILD_NAME}" MATCHES "(^|_)gnu(_|$)")
- set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database" CACHE STRING "")
-endif()
+set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database" CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_clang_common.cmake")
diff --git a/.gitlab/ci/configure_windows_common.cmake b/.gitlab/ci/configure_windows_common.cmake
index 1246885..b243ece 100644
--- a/.gitlab/ci/configure_windows_common.cmake
+++ b/.gitlab/ci/configure_windows_common.cmake
@@ -3,6 +3,7 @@
set(CMAKE_PREFIX_PATH "$ENV{CI_PROJECT_DIR}/.gitlab/qt" CACHE STRING "")
set(CMake_TEST_Java OFF CACHE BOOL "")
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
+set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
set(Python_FIND_REGISTRY NEVER CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_common.cmake")
diff --git a/.gitlab/ci/configure_windows_orangec6.73.1.cmake b/.gitlab/ci/configure_windows_orangec6.73.8.cmake
similarity index 100%
rename from .gitlab/ci/configure_windows_orangec6.73.1.cmake
rename to .gitlab/ci/configure_windows_orangec6.73.8.cmake
diff --git a/.gitlab/ci/configure_windows_orangec7.0.7.cmake b/.gitlab/ci/configure_windows_orangec7.0.7.cmake
new file mode 100644
index 0000000..e5ca56b
--- /dev/null
+++ b/.gitlab/ci/configure_windows_orangec7.0.7.cmake
@@ -0,0 +1,3 @@
+set(CMake_TEST_C_STANDARDS "90;99;11;23" CACHE STRING "")
+set(CMake_TEST_CXX_STANDARDS "11;14;17" CACHE STRING "")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_orangec_common.cmake")
diff --git a/.gitlab/ci/configure_windows_pellesc13.01.cmake b/.gitlab/ci/configure_windows_pellesc13.01.cmake
new file mode 100644
index 0000000..db8a63c
--- /dev/null
+++ b/.gitlab/ci/configure_windows_pellesc13.01.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_pellesc_common.cmake")
diff --git a/.gitlab/ci/configure_windows_pellesc_common.cmake b/.gitlab/ci/configure_windows_pellesc_common.cmake
new file mode 100644
index 0000000..bc2cc51
--- /dev/null
+++ b/.gitlab/ci/configure_windows_pellesc_common.cmake
@@ -0,0 +1,6 @@
+set(CMake_TEST_CXX OFF CACHE BOOL "")
+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/ctest_exclusions.cmake b/.gitlab/ci/ctest_exclusions.cmake
index e04dea3..c4f6fd8 100644
--- a/.gitlab/ci/ctest_exclusions.cmake
+++ b/.gitlab/ci/ctest_exclusions.cmake
@@ -49,6 +49,24 @@
)
endif()
+if ("$ENV{CMAKE_CONFIGURATION}" MATCHES [[windows_orangec7\.0\.7]])
+ list(APPEND test_exclusions
+ # FIXME(OrangeC#1136): OrangeC 7 no longer fails when linking a missing library
+ "^RunCMake.CheckModules$"
+ )
+endif()
+
+if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "windows_clang_fastbuild")
+ list(APPEND test_exclusions
+ # FIXME(#27697): These fail with clang-cl and FASTBuild.
+ "^BuildDepends$"
+ "^ExportImport$"
+ "^Module.CheckIPOSupported-C$"
+ "^RunCMake.PrecompileHeaders$"
+ "^RunCMake.PrecompileHeaders-Reuse$"
+ )
+endif()
+
string(REPLACE ";" "|" test_exclusions "${test_exclusions}")
if (test_exclusions)
set(test_exclusions "(${test_exclusions})")
diff --git a/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile b/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile
deleted file mode 100644
index 7f6e297..0000000
--- a/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM fedora:41
-MAINTAINER Ben Boeckel <ben.boeckel@kitware.com>
-
-# Install build dependencies for packages.
-COPY install_deps.sh /root/install_deps.sh
-RUN sh /root/install_deps.sh
-
-COPY install_gcc.sh /root/install_gcc.sh
-RUN sh /root/install_gcc.sh
diff --git a/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh b/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh
deleted file mode 100755
index b8b706b..0000000
--- a/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-set -e
-
-dnf install -y --setopt=install_weak_deps=False \
- gcc-c++ mpfr-devel libmpc-devel isl-devel flex bison file findutils diffutils git-core
-dnf clean all
diff --git a/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh b/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh
deleted file mode 100755
index 32cb9ec..0000000
--- a/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-set -e
-
-readonly revision="10e702789eeabcc88451e34c2a5c7dccb96190a5" # master as of 21 Nov 2024
-readonly tarball="git://gcc.gnu.org/git/gcc.git"
-
-readonly workdir="$HOME/gcc"
-readonly srcdir="$workdir/gcc"
-readonly builddir="$workdir/build"
-readonly njobs="$( nproc )"
-
-mkdir -p "$workdir"
-cd "$workdir"
-git clone "$tarball" "$srcdir"
-git -C "$srcdir" checkout "$revision"
-mkdir -p "$builddir"
-cd "$builddir"
-"$srcdir/configure" \
- --disable-multilib \
- --enable-languages=c,c++ \
- --prefix="/opt/gcc-importstd"
-make "-j$njobs"
-make "-j$njobs" install-strip
-rm -rf "$workdir"
diff --git a/.gitlab/ci/docker/nvhpc24.9/Dockerfile b/.gitlab/ci/docker/nvhpc24.9/Dockerfile
deleted file mode 100644
index b94b14a..0000000
--- a/.gitlab/ci/docker/nvhpc24.9/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-# https://catalog.ngc.nvidia.com/orgs/nvidia/containers/nvhpc/tags
-FROM kitware/nvidia-nvhpc:24.9-devel-cuda_multi-ubuntu24.04
-MAINTAINER Brad King <brad.king@kitware.com>
-
-COPY install_deps.sh /root/install_deps.sh
-RUN sh /root/install_deps.sh
diff --git a/.gitlab/ci/docker/nvhpc26.3/Dockerfile b/.gitlab/ci/docker/nvhpc26.3/Dockerfile
new file mode 100644
index 0000000..14b9bca
--- /dev/null
+++ b/.gitlab/ci/docker/nvhpc26.3/Dockerfile
@@ -0,0 +1,6 @@
+# https://catalog.ngc.nvidia.com/orgs/nvidia/containers/nvhpc/tags
+FROM kitware/nvidia-nvhpc:26.3-devel-cuda_multi-ubuntu24.04
+MAINTAINER Brad King <brad.king@kitware.com>
+
+COPY install_deps.sh /root/install_deps.sh
+RUN sh /root/install_deps.sh
diff --git a/.gitlab/ci/docker/nvhpc24.9/install_deps.sh b/.gitlab/ci/docker/nvhpc26.3/install_deps.sh
similarity index 100%
rename from .gitlab/ci/docker/nvhpc24.9/install_deps.sh
rename to .gitlab/ci/docker/nvhpc26.3/install_deps.sh
diff --git a/.gitlab/ci/env_fedora43_ninja.sh b/.gitlab/ci/env_fedora43_ninja.sh
index 0ef4bce..18c2158 100644
--- a/.gitlab/ci/env_fedora43_ninja.sh
+++ b/.gitlab/ci/env_fedora43_ninja.sh
@@ -3,5 +3,12 @@
source .gitlab/ci/ispc-env.sh
fi
+# This job builds CMake as C++11. Prevent C++17 headers from being used.
+if test "$CMAKE_CONFIGURATION" = "fedora43_ninja" -a "$CI_JOB_STAGE" = "build"; then
+ for i in filesystem optional string_view; do
+ sed -i -e '$a#error "Use <cm/'"$i"'> instead"' "/usr/include/c++/15/$i"
+ done
+fi
+
# Test in a UTF-8 locale.
export LANG=en_US.UTF-8
diff --git a/.gitlab/ci/env_fedora43_ninja_gcc_std_reloc.sh b/.gitlab/ci/env_fedora43_ninja_gcc_std_reloc.sh
new file mode 100644
index 0000000..91b824d
--- /dev/null
+++ b/.gitlab/ci/env_fedora43_ninja_gcc_std_reloc.sh
@@ -0,0 +1,7 @@
+# "Misplace" the `libstdc++.modules.json` file so that
+# `CMAKE_CXX_STDLIB_MODULES_JSON` is needed to use `import std`.
+stdlib_modules_dir="/usr/lib/gcc/x86_64-redhat-linux/15"
+mkdir "$stdlib_modules_dir.reloc"
+mv "$stdlib_modules_dir/libstdc++.modules.json" "$stdlib_modules_dir.reloc"
+export CMAKE_CI_CXX_STDLIB_MODULES_JSON="$stdlib_modules_dir.reloc/libstdc++.modules.json"
+unset stdlib_modules_dir
diff --git a/.gitlab/ci/env_windows_clang_fastbuild.ps1 b/.gitlab/ci/env_windows_clang_fastbuild.ps1
new file mode 100644
index 0000000..e6c1235
--- /dev/null
+++ b/.gitlab/ci/env_windows_clang_fastbuild.ps1
@@ -0,0 +1,2 @@
+. .gitlab/ci/fastbuild-env.ps1
+. .gitlab/ci/clang-env.ps1
diff --git a/.gitlab/ci/env_windows_orangec6.73.1.ps1 b/.gitlab/ci/env_windows_orangec6.73.8.ps1
similarity index 100%
rename from .gitlab/ci/env_windows_orangec6.73.1.ps1
rename to .gitlab/ci/env_windows_orangec6.73.8.ps1
diff --git a/.gitlab/ci/env_windows_orangec6.73.1.ps1 b/.gitlab/ci/env_windows_orangec7.0.7.ps1
similarity index 100%
copy from .gitlab/ci/env_windows_orangec6.73.1.ps1
copy to .gitlab/ci/env_windows_orangec7.0.7.ps1
diff --git a/.gitlab/ci/env_windows_pellesc13.01.ps1 b/.gitlab/ci/env_windows_pellesc13.01.ps1
new file mode 100644
index 0000000..4a8b1ca
--- /dev/null
+++ b/.gitlab/ci/env_windows_pellesc13.01.ps1
@@ -0,0 +1,6 @@
+. .gitlab/ci/ninja-env.ps1
+. .gitlab/ci/pellesc-env.ps1
+
+# FIXME(#21536): Avoid requiring the end user to enable
+# Pelles C's Microsoft extensions to use Windows APIs.
+$env:CFLAGS = "-Ze"
diff --git a/.gitlab/ci/orangec.ps1 b/.gitlab/ci/orangec.ps1
index 2201e12..0216fff 100644
--- a/.gitlab/ci/orangec.ps1
+++ b/.gitlab/ci/orangec.ps1
@@ -1,9 +1,14 @@
$erroractionpreference = "stop"
-if ("$env:CMAKE_CONFIGURATION".Contains("orangec6.73.1")) {
- # OrangeC 6.73.1
+if ("$env:CMAKE_CONFIGURATION".Contains("orangec7.0.7")) {
+ # OrangeC 7.0.7
+ $archive = "ZippedBinaries707.zip"
+ $release = "v7.0.7"
+ $sha256sum = "853DDE0F4819E65E3EC8F94F67C88C07062F3736BF534D2834FDEFCCE3A0B598"
+} elseif ("$env:CMAKE_CONFIGURATION".Contains("orangec6.73.8")) {
+ # OrangeC 6.73.8
$archive = "ZippedBinaries6738.zip"
- $release = "Orange-C-v6.73.1"
+ $release = "Orange-C-v6.73.1" # release numbering seems mismatched
$sha256sum = "29BC506AB105B2BF1002129C37826B2153DF1C8D0F22B9A2C38ACA3FB72A5B89"
} else {
throw ('unknown CMAKE_CONFIGURATION: ' + "$env:CMAKE_CONFIGURATION")
diff --git a/.gitlab/ci/pellesc-env.ps1 b/.gitlab/ci/pellesc-env.ps1
new file mode 100644
index 0000000..23b8a62
--- /dev/null
+++ b/.gitlab/ci/pellesc-env.ps1
@@ -0,0 +1,6 @@
+& "$pwsh" -File ".gitlab/ci/pellesc.ps1"
+Invoke-Expression -Command .gitlab/ci/pellesc-vars.ps1
+
+$env:CC = "pocc"
+$env:CXX = "pocc-does-not-support-c++"
+pocc | Select -First 1
diff --git a/.gitlab/ci/pellesc-vars.ps1 b/.gitlab/ci/pellesc-vars.ps1
new file mode 100644
index 0000000..457ddb1
--- /dev/null
+++ b/.gitlab/ci/pellesc-vars.ps1
@@ -0,0 +1,7 @@
+$erroractionpreference = "stop"
+
+$all_env = cmd /c "`".gitlab\pellesc\bin\povars64.bat`" >NUL & powershell -Command `"Get-ChildItem env: | Select-Object -Property Key,Value | ConvertTo-Json`"" | ConvertFrom-Json
+
+foreach ($envvar in $all_env) {
+ [Environment]::SetEnvironmentVariable($envvar.Key, $envvar.Value)
+}
diff --git a/.gitlab/ci/pellesc.ps1 b/.gitlab/ci/pellesc.ps1
new file mode 100644
index 0000000..0caacb2
--- /dev/null
+++ b/.gitlab/ci/pellesc.ps1
@@ -0,0 +1,33 @@
+$erroractionpreference = "stop"
+
+if ("$env:CMAKE_CONFIGURATION".Contains("pellesc13.01")) {
+ # PellesC 13.01
+ # https://www.pellesc.se/1300/setup.exe
+ $filename = "pellesc-13.01-1"
+ $sha256sum = "E48AF208D1A46F47490011979538C1DBC427B36D47554A76C3FF83284E8F83AE"
+} else {
+ throw ('unknown CMAKE_CONFIGURATION: ' + "$env:CMAKE_CONFIGURATION")
+}
+$archive = "$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/$archive" -OutFile "$outdir\$archive"
+$hash = Get-FileHash "$outdir\$archive" -Algorithm SHA256
+if ($hash.Hash -ne $sha256sum) {
+ exit 1
+}
+
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+[System.IO.Compression.ZipFile]::ExtractToDirectory("$outdir\$archive", "$outdir")
+Move-Item -Path "$outdir\$filename" -Destination "$outdir\pellesc"
+Remove-Item "$outdir\$archive"
+
+$scripts = "povars32.bat", "povars64.bat"
+foreach ($script in $scripts) {
+ $bat = Get-Content -Path "$outdir\pellesc\bin\$script.in" -Raw
+ $bat = $bat -Replace "@PellesCDir@","$outdir\pellesc"
+ $bat | Set-Content -Path "$outdir\pellesc\bin\$script"
+}
diff --git a/.gitlab/ci/repackage/pellesc.ps1 b/.gitlab/ci/repackage/pellesc.ps1
new file mode 100644
index 0000000..0d10129
--- /dev/null
+++ b/.gitlab/ci/repackage/pellesc.ps1
@@ -0,0 +1,74 @@
+# Pelles C compilers are available only via installers.
+# Run an installer and repackage the installation directory.
+
+# From the Pelles C download page, download "setup.exe".
+# Run this script passing "setup.exe" followed by the version number.
+
+#Requires -RunAsAdministrator
+
+param (
+ [Parameter(Mandatory=$true)]
+ [string]$installer,
+ [Parameter(Mandatory=$true)]
+ [string]$version,
+ [string]$revision = "1",
+ [string]$basedir = "c:\PellesC"
+ )
+
+$erroractionpreference = "stop"
+
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+
+$installer_file = Get-Item $installer
+$installer_name = $installer_file.Name
+$package_name = "pellesc-$version-$revision"
+$package_dir = New-Item -Force -ItemType Directory -Path "$basedir\$package_name"
+if (-not $package_dir) {
+ Write-Host "Failed to create package install dir."
+ Exit 1
+}
+
+Write-Host "Installing to: $package_dir"
+
+# The installer treats everything after /D= as the destination.
+# Start-Process adds a trailing space, so use "cmd" instead.
+& "$env:ComSpec" /c start /wait "$installer_file" /S /D=$package_dir
+Write-Host ""
+Remove-Item "$package_dir/uninst.exe" -Force
+
+# Convert environment scripts to templates.
+$bats = @(
+ "bin\povars32.bat"
+ "bin\povars64.bat"
+ )
+foreach ($p in $bats) {
+ $bat = Get-Content -Path "$package_dir\$p" -Raw
+ $bat = $bat -Replace "PellesCDir=.*","PellesCDir=@PellesCDir@"
+ $bat | Set-Content -Path "$package_dir\$p.in"
+ Remove-Item "$package_dir\$p" -Force
+}
+
+@"
+This was repackaged from an installation by
+
+ Pelles C $version "$installer_name"
+
+using CMake's ".gitlab/ci/repackage/pellesc.ps1" script.
+
+Copy or rename the environment script templates in the "bin" directory:
+
+ povars32.bat.in => povars32.bat
+ povars64.bat.in => povars64.bat
+
+and replace the "@PellesCDir@" placeholders with
+
+ C:\path\to\this\directory
+
+Then use "povars32.bat" or "povars64.bat" to establish an environment.
+
+"@ | Add-Content -NoNewline "$package_dir/README.txt"
+
+Write-Host "Repackaging to: $package_name.zip"
+$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
+$includeBaseDirectory = $true
+[System.IO.Compression.ZipFile]::CreateFromDirectory("$package_dir", "$package_name.zip", $compressionLevel, $includeBaseDirectory)
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 7ec2288..5e6f1ee 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -331,6 +331,13 @@
variables:
CMAKE_CONFIGURATION: fedora43_ninja_clang
+.fedora43_ninja_gcc_std_reloc:
+ extends: .fedora43
+
+ variables:
+ CMAKE_CONFIGURATION: fedora43_ninja_gcc_std_reloc
+ CTEST_LABELS: "CXXModules"
+
.fedora43_ninja_multi_clang:
extends: .fedora43
@@ -400,7 +407,7 @@
### NVHPC Compiler
.nvhpc:
- image: "kitware/cmake:ci-nvhpc24.9-x86_64-2024-09-27"
+ image: "kitware/cmake:ci-nvhpc26.3-x86_64-2026-03-31"
variables:
CMAKE_ARCH: x86_64
CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP: 1
@@ -599,37 +606,6 @@
CTEST_LABELS: "HIP"
CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP: 1
-### C++ modules
-
-.gcc_cxx_modules_x86_64:
- image: "kitware/cmake:ci-gcc_cxx_modules-x86_64-2024-12-23"
-
- variables:
- GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
- CMAKE_ARCH: x86_64
- CC: "/opt/gcc-importstd/bin/gcc"
- CXX: "/opt/gcc-importstd/bin/g++"
-
-.gcc_cxx_modules_ninja:
- extends: .gcc_cxx_modules_x86_64
-
- variables:
- CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja
-
-.gcc_cxx_modules_reloc_ninja:
- extends: .gcc_cxx_modules_x86_64
-
- variables:
- CMAKE_CONFIGURATION: linux_gcc_cxx_modules_reloc_ninja
- CTEST_LABELS: "CXXModules"
-
-.gcc_cxx_modules_ninja_multi:
- extends: .gcc_cxx_modules_x86_64
-
- variables:
- CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja_multi
- CMAKE_GENERATOR: "Ninja Multi-Config"
-
### Debian 10 legacy packages
.debian10:
@@ -690,10 +666,10 @@
- docker
- linux-x86_64
-.linux_x86_64_v3_tags_cuda_arch_52:
+.linux_x86_64_v3_tags_cuda_arch_75:
tags:
- cmake
- - cuda-arch-52
+ - cuda-arch-75
- docker
- linux-x86_64-v3
diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml
index 55bc515..5cea2ed 100644
--- a/.gitlab/os-windows.yml
+++ b/.gitlab/os-windows.yml
@@ -243,6 +243,14 @@
variables:
CMAKE_CONFIGURATION: windows_vs2026_x64_fastbuild
+.windows_clang_fastbuild:
+ extends:
+ - .windows_fastbuild
+ - .windows_vcvarsall_vs2022_x64_msvc14.44
+
+ variables:
+ CMAKE_CONFIGURATION: windows_clang_fastbuild
+
.windows_clang_ninja:
extends:
- .windows_ninja
@@ -305,11 +313,32 @@
CMAKE_CI_BUILD_TYPE: Release
CMAKE_CI_JOB_NIGHTLY_IGNORE_DEPS: "true"
-.windows_orangec6.73.1:
+.windows_orangec6.73.8:
extends: .windows_orangec
variables:
- CMAKE_CONFIGURATION: windows_orangec6.73.1
+ CMAKE_CONFIGURATION: windows_orangec6.73.8
+
+.windows_orangec7.0.7:
+ extends: .windows_orangec
+
+ variables:
+ CMAKE_CONFIGURATION: windows_orangec7.0.7
+
+.windows_pellesc:
+ extends: .windows
+
+ variables:
+ CMAKE_GENERATOR: "Ninja"
+ CMAKE_CI_BUILD_TYPE: Release
+ CMAKE_CI_JOB_NIGHTLY_IGNORE_DEPS: "true"
+ CTEST_LABELS: "PellesC"
+
+.windows_pellesc13.01:
+ extends: .windows_pellesc
+
+ variables:
+ CMAKE_CONFIGURATION: windows_pellesc13.01
.windows_arm64_vs2026:
extends: .windows
diff --git a/Auxiliary/bash-completion/cmake b/Auxiliary/bash-completion/cmake
index 3c30d34..c46e02a 100644
--- a/Auxiliary/bash-completion/cmake
+++ b/Auxiliary/bash-completion/cmake
@@ -114,6 +114,31 @@
_filedir -d
return
;;
+
+ --target)
+ local quoted
+ printf -v quoted %q "$cur"
+ # Options allowed right after `--target`
+ local target_options='--verbose --clean-first --config --'
+ local build_dir="build"
+ for ((i=0; i < ${#COMP_WORDS[@]}; i++)); do
+ if [[ "${COMP_WORDS[i]}" == "--build" ]]; then
+ build_dir="${COMP_WORDS[i+1]}"
+ break
+ fi
+ done
+ if [[ "$cur" == -* ]]; then
+ COMPREPLY=( $( compgen -W "$target_options" -- "$quoted" ) )
+ else
+ local targets=$( cmake --build "$build_dir" --target help 2>/dev/null \
+ | sed -n -e 's/^... \([^ ]*\).*$/\1/p' \
+ -e '/^\[/d' -e 's/^\([^ :]*\):.*$/\1/p' | \
+ grep -v '^/' | sort -u )
+ COMPREPLY=( $( compgen -W "$targets $target_options" -- "$quoted" ) )
+ fi
+ return
+ ;;
+
--install|--open)
_filedir -d
return
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8252775..06778c7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,13 +1,33 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
-cmake_minimum_required(VERSION 3.13...4.1 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.13...4.2 FATAL_ERROR)
+
+if(CMake_TEST_HOST_CMAKE)
+ get_filename_component(CMake_TEST_EXTERNAL_CMAKE "${CMAKE_COMMAND}" DIRECTORY)
+endif()
+
+set(CMake_LANGUAGES "")
+if(CMake_TEST_EXTERNAL_CMAKE)
+ foreach(lang C CXX)
+ if(NOT DEFINED CMake_TEST_${lang})
+ set(CMake_TEST_${lang} 1)
+ endif()
+ if(CMake_TEST_${lang})
+ list(APPEND CMake_LANGUAGES ${lang})
+ endif()
+ endforeach()
+else()
+ set(CMake_TEST_C 1)
+ set(CMake_TEST_CXX 1)
+ list(APPEND CMake_LANGUAGES C CXX)
+endif()
set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake)
-
-project(CMake)
+project(CMake LANGUAGES ${CMake_LANGUAGES})
unset(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX)
unset(CMAKE_USER_MAKE_RULES_OVERRIDE_C)
+unset(CMake_LANGUAGES)
# FIXME: This block should go away after a transition period.
if(MSVC AND NOT CMAKE_VERSION VERSION_LESS 3.15)
@@ -30,10 +50,6 @@
unset(CMAKE_BOOTSTRAP CACHE)
endif()
-if(CMake_TEST_HOST_CMAKE)
- get_filename_component(CMake_TEST_EXTERNAL_CMAKE "${CMAKE_COMMAND}" DIRECTORY)
-endif()
-
if(NOT CMake_TEST_EXTERNAL_CMAKE)
if(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
message(FATAL_ERROR
@@ -466,6 +482,7 @@
if(CMake_TEST_EXTERNAL_CMAKE)
set(KWIML_TEST_ENABLE 1)
+ set(KWIML_TEST_LABELS "PellesC")
add_subdirectory(Utilities/KWIML)
endif()
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 7247467..7b918dc 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -45,6 +45,9 @@
The merge request will enter the `CMake Review Process`_ for consideration.
+Please note `CMake's AI policy`_ if using AI tools or services as part of
+preparing or submitting a change.
+
.. _`Kitware's GitLab Instance`: https://gitlab.kitware.com
.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake
.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh
@@ -53,6 +56,7 @@
.. _`CMake Testing Guide`: Help/dev/testing.rst
.. _`commit messages`: Help/dev/review.rst#commit-messages
.. _`CMake Review Process`: Help/dev/review.rst
+.. _`CMake's AI policy`: Help/dev/ai-policy.rst
CMake Dashboard Client
======================
diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst
index d4d030e..cd5479a 100644
--- a/CONTRIBUTORS.rst
+++ b/CONTRIBUTORS.rst
@@ -64,6 +64,7 @@
* `Petr Gotthard <mailto:gotthard@honeywell.com>`__
* `Philip Lowman <mailto:philip@yhbt.com>`__
* `Philippe Proulx <mailto:pproulx@efficios.com>`__
+* `Qualcomm Technologies, Inc. <https://www.qualcomm.com>`__
* Raffi Enficiaud, Max Planck Society
* Raumfeld
* `Roger Leigh <mailto:rleigh@codelibre.net>`__
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index cb18bcc..4dc92b2 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -188,6 +188,12 @@
cause the custom command to re-run whenever the target is
recompiled.
+ .. versionchanged:: 4.4
+
+ Previously an executable target could be specified using the name
+ of the target with ``.exe`` appended. This is no longer allowed.
+ See policy :policy:`CMP0212`.
+
2. If the argument is an absolute path, a file-level dependency
is created on that path.
diff --git a/Help/command/block.rst b/Help/command/block.rst
index 7b5b581..abdbd37 100644
--- a/Help/command/block.rst
+++ b/Help/command/block.rst
@@ -7,7 +7,8 @@
.. code-block:: cmake
- block([SCOPE_FOR [POLICIES] [VARIABLES]] [PROPAGATE <var-name>...])
+ block([SCOPE_FOR [DIAGNOSTICS] [POLICIES] [VARIABLES]]
+ [PROPAGATE <var-name>...])
<commands>
endblock()
@@ -19,6 +20,13 @@
``SCOPE_FOR``
Specify which scopes must be created.
+ ``DIAGNOSTICS``
+ .. versionadded:: 4.4
+
+ Create a new diagnostic scope. This is equivalent to
+ :command:`cmake_diagnostic(PUSH)` with an automatic
+ :command:`cmake_diagnostic(POP)` when leaving the block scope.
+
``POLICIES``
Create a new policy scope. This is equivalent to
:command:`cmake_policy(PUSH)` with an automatic
@@ -31,7 +39,7 @@
.. code-block:: cmake
- block(SCOPE_FOR VARIABLES POLICIES)
+ block(SCOPE_FOR VARIABLES POLICIES DIAGNOSTICS)
``PROPAGATE``
When a variable scope is created by the :command:`block` command, this
diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst
index 21adab9..6bb7d58 100644
--- a/Help/command/build_command.rst
+++ b/Help/command/build_command.rst
@@ -29,7 +29,7 @@
.. versionadded:: 3.21
The ``PARALLEL_LEVEL`` argument can be used to set the
- :option:`--parallel <cmake--build --parallel>` flag.
+ :cmake-build-option:`--parallel` flag.
.. code-block:: cmake
@@ -39,7 +39,7 @@
compatibility. Use the first signature instead.
It sets the given ``<cachevariable>`` to a command-line string as
-above but without the :option:`--target <cmake--build --target>` option.
+above but without the :cmake-build-option:`--target` option.
The ``<makecommand>`` is ignored but should be the full path to
devenv, nmake, make or one of the end user build tools
for legacy invocations.
diff --git a/Help/command/cmake_diagnostic.rst b/Help/command/cmake_diagnostic.rst
new file mode 100644
index 0000000..29b2589
--- /dev/null
+++ b/Help/command/cmake_diagnostic.rst
@@ -0,0 +1,156 @@
+cmake_diagnostic
+----------------
+
+.. versionadded:: 4.4
+
+Manage CMake Diagnostic settings. See the :manual:`cmake-diagnostics(7)`
+manual for a list of available categories.
+
+Synopsis
+^^^^^^^^
+
+.. parsed-literal::
+
+ `Setting Diagnostics`_
+ cmake_diagnostic(`SET`_ <category> <action> [RECURSE])
+ cmake_diagnostic(`PROMOTE`_ <category> <action> [NO_RECURSE])
+ cmake_diagnostic(`DEMOTE`_ <category> <action> [NO_RECURSE])
+
+ `Checking Diagnostic Actions`_
+ cmake_diagnostic(`GET`_ <diagnostic> <out-var>)
+
+ `CMake Diagnostic Stack`_
+ cmake_diagnostic(`PUSH`_)
+ cmake_diagnostic(`POP`_)
+
+Setting Diagnostics
+^^^^^^^^^^^^^^^^^^^
+
+.. signature::
+ cmake_diagnostic(SET CMD_<CATEGORY> <action> [RECURSE])
+ cmake_diagnostic(PROMOTE CMD_<CATEGORY> <action> [NO_RECURSE])
+ cmake_diagnostic(DEMOTE CMD_<CATEGORY> <action> [NO_RECURSE])
+ :target:
+ SET
+ PROMOTE
+ DEMOTE
+
+Set or alter the action taken when a diagnostic belonging to a particular
+category is triggered.
+
+The ``SET`` subcommand sets the action for the specified diagnostic category.
+The ``PROMOTE`` subcommand increases the severity for the specified diagnostic
+category, or does nothing if the action was already set to an equal or higher
+severity. The ``DEMOTE`` subcommand decreases the severity for the specified
+diagnostic category, or does nothing if the action was already set to an equal
+or lower severity.
+
+The possible ``<action>``\ s (in order of severity) are:
+
+``IGNORE``
+ Do nothing.
+
+``WARN``
+ Report a warning and continue processing.
+
+``SEND_ERROR``
+ Report an error, continue processing, but skip generation.
+
+ The :manual:`cmake(1)` executable will return a non-zero
+ :ref:`exit code <CMake Exit Code>`.
+
+``FATAL_ERROR``
+ Report an error, stop processing and generation.
+
+ The :manual:`cmake(1)` executable will return a non-zero
+ :ref:`exit code <CMake Exit Code>`.
+
+Some diagnostic categories are hierarchical. The ``RECURSE`` and
+``NO_RECURSE`` options determine whether changing the action for a diagnostic
+category also modifies any child categories. By default, the ``PROMOTE`` and
+``DEMOTE`` subcommands are recursive, while the ``SET`` subcommand is not.
+Note that the alteration for child categories is independent of the prior
+action set on any parents; that is, ``PROMOTE`` and ``DEMOTE``, when operating
+recursively, will operate on all child categories even if a parent category's
+action was not altered.
+
+Checking Diagnostic Actions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. signature:: cmake_diagnostic(GET CMD_<CATEGORY> <variable>)
+ :target: GET
+
+Check what action is currently specified for a diagnostic category.
+The output ``<variable>`` value will be one of ``IGNORE``, ``WARN``,
+``SEND_ERROR`` or ``FATAL_ERROR``.
+
+CMake Diagnostic Stack
+^^^^^^^^^^^^^^^^^^^^^^
+
+CMake keeps diagnostic settings on a stack, so changes made by the
+``cmake_diagnostic`` command affect only the top of the stack. A new entry on
+the diagnostic stack is managed automatically for each subdirectory to protect
+its parents and siblings. CMake also manages a new entry for scripts loaded by
+:command:`include` and :command:`find_package` commands except when invoked
+with the ``NO_DIAGNOSTIC_SCOPE`` option. The ``cmake_diagnostic`` command
+provides an interface to manage custom entries on the diagnostic stack:
+
+.. signature:: cmake_diagnostic(PUSH)
+
+ Create a new entry on the diagnostic stack.
+
+.. signature:: cmake_diagnostic(POP)
+
+ Remove the last diagnostic stack entry created with
+ ``cmake_diagnostic(PUSH)``.
+
+Each ``PUSH`` must have a matching ``POP`` to erase any changes.
+This is useful to make temporary changes to diagnostic settings.
+Calls to the :command:`cmake_diagnostic(SET)`,
+:command:`cmake_diagnostic(PROMOTE)`, or :command:`cmake_diagnostic(DEMOTE)`
+commands influence only the current top of the diagnostic stack.
+
+The :command:`block(SCOPE_FOR DIAGNOSTICS)` command offers a more flexible
+and more secure way to manage the diagnostic stack. The pop action is done
+automatically when leaving the block scope, so there is no need to
+precede each :command:`return` with a call to :command:`cmake_diagnostic(POP)`.
+
+.. code-block:: cmake
+
+ # stack management with cmake_diagnostic()
+ function(my_func)
+ cmake_diagnostic(PUSH)
+ cmake_diagnostic(SET ...)
+ if (<cond1>)
+ ...
+ cmake_diagnostic(POP)
+ return()
+ elseif(<cond2>)
+ ...
+ cmake_diagnostic(POP)
+ return()
+ endif()
+ ...
+ cmake_diagnostic(POP)
+ endfunction()
+
+ # stack management with block()/endblock()
+ function(my_func)
+ block(SCOPE_FOR DIAGNOSTICS)
+ cmake_diagnostic(SET ...)
+ if (<cond1>)
+ ...
+ return()
+ elseif(<cond2>)
+ ...
+ return()
+ endif()
+ ...
+ endblock()
+ endfunction()
+
+Commands created by the :command:`function` and :command:`macro` commands
+record diagnostic settings when they are created and use the pre-record
+diagnostics when they are invoked. If the function or macro implementation
+sets diagnostics, the changes automatically propagate up through callers until
+they reach the closest nested diagnostic stack entry.
diff --git a/Help/command/create_test_sourcelist.rst b/Help/command/create_test_sourcelist.rst
index d0b43c4..f3aca7a 100644
--- a/Help/command/create_test_sourcelist.rst
+++ b/Help/command/create_test_sourcelist.rst
@@ -60,3 +60,44 @@
.. variable:: CMAKE_TESTDRIVER_AFTER_TESTMAIN
Code to be placed directly after the call to each test's function.
+
+The generated test driver supports the following command-line arguments:
+
+``<name>``
+ Run the test with the exact name ``<name>`` (case-insensitive).
+
+``-R <substr>``
+ Run the first test whose name contains ``<substr>`` (case-insensitive).
+
+``-A [<skip_test>...]``
+ .. versionadded:: 3.21
+
+ Run all tests and print results in `TAP <https://testanything.org/>`_
+ format.
+
+ Any additional arguments after ``-A`` are interpreted as exact test names
+ to skip.
+
+``-N``
+ .. versionadded:: 4.4
+
+ List all available test names (one per line) and exit.
+
+Example
+^^^^^^^
+
+.. code-block:: cmake
+
+ create_test_sourcelist(SRCS main.c test1.c test2.c)
+ add_executable(MyTests ${SRCS})
+ discover_tests(COMMAND MyTests
+ DISCOVERY_ARGS -N
+ DISCOVERY_MATCH "^(.+)$"
+ TEST_NAME "${PROJECT_NAME}.\\1"
+ TEST_ARGS "\\1"
+ )
+
+See Also
+^^^^^^^^
+
+* :command:`discover_tests`
diff --git a/Help/command/ctest_configure.rst b/Help/command/ctest_configure.rst
index f23dd22..d9b77a9 100644
--- a/Help/command/ctest_configure.rst
+++ b/Help/command/ctest_configure.rst
@@ -30,7 +30,8 @@
produced by a previous call to this command.
``OPTIONS <options>``
- Specify command-line arguments to pass to the configuration tool.
+ Specify a :ref:`semicolon-separated list <CMake Language Lists>` of
+ command-line arguments to pass to the configuration tool.
``RETURN_VALUE <result-var>``
Store in the ``<result-var>`` variable the return value of the native
@@ -39,8 +40,9 @@
``CAPTURE_CMAKE_ERROR <result-var>``
.. versionadded:: 3.7
- Store in the ``<result-var>`` variable -1 if there are any errors running
- the command and prevent ctest from returning non-zero if an error occurs.
+ Store in the ``<result-var>`` variable ``-1`` if there are any errors running
+ the command and prevent :manual:`ctest(1)` from returning non-zero if an
+ error occurs.
``QUIET``
.. versionadded:: 3.3
diff --git a/Help/command/ctest_coverage.rst b/Help/command/ctest_coverage.rst
index 319c978..5a85007 100644
--- a/Help/command/ctest_coverage.rst
+++ b/Help/command/ctest_coverage.rst
@@ -39,8 +39,9 @@
``CAPTURE_CMAKE_ERROR <result-var>``
.. versionadded:: 3.7
- Store in the ``<result-var>`` variable -1 if there are any errors running
- the command and prevent ctest from returning non-zero if an error occurs.
+ Store in the ``<result-var>`` variable ``-1`` if there are any errors running
+ the command and prevent :manual:`ctest(1)` from returning non-zero if an
+ error occurs.
``QUIET``
.. versionadded:: 3.3
diff --git a/Help/command/ctest_empty_binary_directory.rst b/Help/command/ctest_empty_binary_directory.rst
index 5d26de1..1f91d0c 100644
--- a/Help/command/ctest_empty_binary_directory.rst
+++ b/Help/command/ctest_empty_binary_directory.rst
@@ -1,7 +1,7 @@
ctest_empty_binary_directory
----------------------------
-empties the binary directory
+Empties the binary directory.
.. code-block:: cmake
diff --git a/Help/command/ctest_read_custom_files.rst b/Help/command/ctest_read_custom_files.rst
index 53c093e..48b2060 100644
--- a/Help/command/ctest_read_custom_files.rst
+++ b/Help/command/ctest_read_custom_files.rst
@@ -1,13 +1,13 @@
ctest_read_custom_files
-----------------------
-read CTestCustom files.
+Read CTestCustom files.
.. code-block:: cmake
ctest_read_custom_files(<directory>...)
-Read all the CTestCustom.ctest or CTestCustom.cmake files from the
+Read all the ``CTestCustom.ctest`` or ``CTestCustom.cmake`` files from the
given directory.
By default, invoking :manual:`ctest(1)` without a script will read custom
diff --git a/Help/command/ctest_run_script.rst b/Help/command/ctest_run_script.rst
index 0d94eb0..734fa28 100644
--- a/Help/command/ctest_run_script.rst
+++ b/Help/command/ctest_run_script.rst
@@ -1,14 +1,21 @@
ctest_run_script
----------------
-runs a :option:`ctest -S` script
+Run a :option:`ctest -S` script.
.. code-block:: cmake
- ctest_run_script([NEW_PROCESS] script_file_name script_file_name1
- script_file_name2 ... [RETURN_VALUE var])
+ ctest_run_script([NEW_PROCESS]
+ <script-file>...
+ [RETURN_VALUE <result-var>]
+ )
Runs a script or scripts much like if it was run from :option:`ctest -S`.
-If ``NEW_PROCESS`` is specified then each script will be run in a separate
-process. If ``RETURN_VALUE`` is specified the return value of the last script
-run will be put into ``var``.
+The options are:
+
+``NEW_PROCESS``
+ Run each script in a separate process.
+
+``RETURN_VALUE <result-var>``
+ Store in the ``<result-var>`` variable ``0`` for success and
+ non-zero on failure.
diff --git a/Help/command/ctest_sleep.rst b/Help/command/ctest_sleep.rst
index 42b9768..723c2d4 100644
--- a/Help/command/ctest_sleep.rst
+++ b/Help/command/ctest_sleep.rst
@@ -1,16 +1,15 @@
ctest_sleep
-----------
-sleeps for some amount of time
+Sleep for some amount of time.
-.. code-block:: cmake
-
+.. signature::
ctest_sleep(<seconds>)
-Sleep for given number of seconds.
+ Sleep for ``<seconds>`` seconds.
-.. code-block:: cmake
-
+.. signature::
ctest_sleep(<time1> <duration> <time2>)
-Sleep for t=(time1 + duration - time2) seconds if t > 0.
+ Sleep for ``<time1> + <duration> - <time2>`` seconds, if this sum is greater
+ than zero.
diff --git a/Help/command/ctest_start.rst b/Help/command/ctest_start.rst
index 9c4e3dc..9184fac 100644
--- a/Help/command/ctest_start.rst
+++ b/Help/command/ctest_start.rst
@@ -1,7 +1,7 @@
ctest_start
-----------
-Starts the testing for a given model
+Perform the :ref:`CTest Start Step` as a :ref:`Dashboard Client`.
.. code-block:: cmake
diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst
index 56a47e8..aa238b0 100644
--- a/Help/command/ctest_submit.rst
+++ b/Help/command/ctest_submit.rst
@@ -83,8 +83,9 @@
``CAPTURE_CMAKE_ERROR <result-var>``
.. versionadded:: 3.13
- Store in the ``<result-var>`` variable -1 if there are any errors running
- the command and prevent ctest from returning non-zero if an error occurs.
+ Store in the ``<result-var>`` variable ``-1`` if there are any errors running
+ the command and prevent :manual:`ctest(1)` from returning non-zero if an
+ error occurs.
``QUIET``
.. versionadded:: 3.3
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index 8cf7134..ad43cd2 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -109,8 +109,8 @@
.. versionadded:: 3.29
- The ``<level>`` may be omitted, or ``0``, to let ctest use a default
- level of parallelism, or unbounded parallelism, respectively, as
+ The ``<level>`` may be omitted, or ``0``, to let :manual:`ctest(1)` use a
+ default level of parallelism, or unbounded parallelism, respectively, as
documented by the :option:`ctest --parallel` option.
``RESOURCE_SPEC_FILE <file>``
@@ -170,8 +170,9 @@
``CAPTURE_CMAKE_ERROR <result-var>``
.. versionadded:: 3.7
- Store in the ``<result-var>`` variable -1 if there are any errors running
- the command and prevent ctest from returning non-zero if an error occurs.
+ Store in the ``<result-var>`` variable ``-1`` if there are any errors running
+ the command and prevent :manual:`ctest(1)` from returning non-zero if an
+ error occurs.
``OUTPUT_JUNIT <file>``
.. versionadded:: 3.21
@@ -194,9 +195,9 @@
:variable:`CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE` and
:variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variables, along with their
corresponding :manual:`ctest(1)` command line options
-:option:`--test-output-size-passed <ctest --test-output-size-passed>`,
-:option:`--test-output-size-failed <ctest --test-output-size-failed>`, and
-:option:`--test-output-truncation <ctest --test-output-truncation>`.
+:ctest-option:`--test-output-size-passed`,
+:ctest-option:`--test-output-size-failed`, and
+:ctest-option:`--test-output-truncation`.
.. _`Additional Test Measurements`:
diff --git a/Help/command/ctest_update.rst b/Help/command/ctest_update.rst
index 836cdf1..c20b8ae 100644
--- a/Help/command/ctest_update.rst
+++ b/Help/command/ctest_update.rst
@@ -26,14 +26,15 @@
``CAPTURE_CMAKE_ERROR <result-var>``
.. versionadded:: 3.13
- Store in the ``<result-var>`` variable -1 if there are any errors running
- the command and prevent ctest from returning non-zero if an error occurs.
+ Store in the ``<result-var>`` variable ``-1`` if there are any errors running
+ the command and prevent :manual:`ctest(1)` from returning non-zero if an
+ error occurs.
``QUIET``
.. versionadded:: 3.3
- Tell CTest to suppress most non-error messages that it would
- have otherwise printed to the console. CTest will still report
+ Suppress any CTest-specific non-error messages that would have otherwise
+ been printed to the console. CTest will still report
the new revision of the repository and any conflicting files
that were found.
diff --git a/Help/command/ctest_upload.rst b/Help/command/ctest_upload.rst
index 344979a..2c0f8b2 100644
--- a/Help/command/ctest_upload.rst
+++ b/Help/command/ctest_upload.rst
@@ -13,14 +13,15 @@
Specify a list of files to be sent along with the build results to the
dashboard server.
+``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.7
+
+ Store in the ``<result-var>`` variable ``-1`` if there are any errors running
+ the command and prevent :manual:`ctest(1)` from returning non-zero if an
+ error occurs.
+
``QUIET``
.. versionadded:: 3.3
Suppress any CTest-specific non-error output that would have been
printed to the console otherwise.
-
-``CAPTURE_CMAKE_ERROR <result-var>``
- .. versionadded:: 3.7
-
- Store in the ``<result-var>`` variable -1 if there are any errors running
- the command and prevent ctest from returning non-zero if an error occurs.
diff --git a/Help/command/discover_tests.rst b/Help/command/discover_tests.rst
new file mode 100644
index 0000000..39bd192
--- /dev/null
+++ b/Help/command/discover_tests.rst
@@ -0,0 +1,117 @@
+discover_tests
+--------------
+
+Register tests with names and properties discovered at test time by
+:manual:`ctest(1)`.
+
+.. code-block:: cmake
+
+ discover_tests(COMMAND <command> [<arg>...] [COMMAND_EXPAND_LISTS]
+ [CONFIGURATIONS <config>...]
+ DISCOVERY_ARGS <arg>...
+ DISCOVERY_MATCH <regex>
+ [DISCOVERY_PROPERTIES <key> <value> [<key> <value>]...]
+ TEST_NAME <replacement>
+ TEST_ARGS <replacement>...
+ [TEST_PROPERTIES <key> <replacement> [<key> <replacement>]...]
+ )
+
+This command configures test discovery rather than defining a single test at
+configure time. During test execution, :manual:`ctest(1)` runs the specified
+discovery command, parses its output, and registers one or more tests based on
+the provided regular expression and replacement strings.
+
+``discover_tests`` options are:
+
+``COMMAND``
+ Specify the command-line used for test discovery.
+
+ The command is executed by :manual:`ctest(1)` at test time (not by CMake at
+ configure time). With ``DISCOVERY_ARGS`` appended, it must print the list of
+ available tests in a format matched by ``DISCOVERY_MATCH``.
+
+ If ``<command>`` specifies an executable target created by
+ :command:`add_executable`:
+
+ * It will automatically be replaced by the location of the executable
+ created at build time.
+
+ * The target's :prop_tgt:`CROSSCOMPILING_EMULATOR`, if set, will be
+ used to run the command on the host::
+
+ <emulator> <command>
+
+ The emulator is used only when
+ :variable:`cross-compiling <CMAKE_CROSSCOMPILING>`.
+
+ * The target's :prop_tgt:`TEST_LAUNCHER`, if set, will be used to launch the
+ command::
+
+ <launcher> <command>
+
+ If the :prop_tgt:`CROSSCOMPILING_EMULATOR` is also set, both are used::
+
+ <launcher> <emulator> <command>
+
+ The command may be specified using
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+``COMMAND_EXPAND_LISTS``
+ Lists in ``COMMAND`` arguments will be expanded, including those created with
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+``CONFIGURATIONS``
+ Restrict the test discovery only to the named configurations.
+
+``DISCOVERY_ARGS``
+ Additional arguments passed to ``COMMAND`` when performing discovery.
+
+``DISCOVERY_MATCH``
+ Regular expression used to parse each line produced by the discovery command.
+ Capturing groups may be referenced by ``TEST_NAME``, ``TEST_ARGS``, and
+ values in ``TEST_PROPERTIES`` using ``\1``, ``\2``, etc.
+
+``DISCOVERY_PROPERTIES``
+ Specify properties for the discovery run itself.
+
+``TEST_NAME``
+ Replacement string used to generate the test name for each discovered test.
+ It may reference capture groups from ``DISCOVERY_MATCH``.
+
+``TEST_ARGS``
+ Replacement strings used to generate the arguments passed to the discovered
+ test. Each argument may reference capture groups from ``DISCOVERY_MATCH``.
+
+``TEST_PROPERTIES``
+ Specify test properties to set on each discovered test. Values are
+ replacement strings and may reference capture groups from
+ ``DISCOVERY_MATCH``.
+
+CTest executes the discovery step to obtain the list of tests and then runs
+each discovered test using the command-line produced by ``COMMAND`` together
+with ``TEST_ARGS``. The pass/fail behavior of each discovered test follows
+the usual CTest rules (exit code ``0`` indicates success unless inverted by
+the :prop_test:`WILL_FAIL` property). Output written to stdout or stderr is
+captured by :manual:`ctest(1)` and only affects the pass/fail status via the
+:prop_test:`PASS_REGULAR_EXPRESSION`, :prop_test:`FAIL_REGULAR_EXPRESSION`,
+or :prop_test:`SKIP_REGULAR_EXPRESSION` test properties.
+
+Example usage:
+
+.. code-block:: cmake
+
+ discover_tests(COMMAND testDriver --exe $<TARGET_FILE:myexe>
+ DISCOVERY_ARGS --list-tests
+ DISCOVERY_MATCH "^([^,]+),([^,]+),([^,]+),(.*)$"
+ TEST_NAME "${PROJECT_NAME}.\\1.\\2"
+ TEST_ARGS --run-test "\\1.\\2"
+ TEST_PROPERTIES
+ PROCESSORS "\\3"
+ LABELS "\\4"
+ )
+
+This example configures discovery by running ``testDriver --list-tests``.
+For each line of output that matches ``DISCOVERY_MATCH``, a test name is
+generated using ``TEST_NAME``, the per-test command-line is generated using
+``TEST_ARGS``, and test properties are populated from the remaining capture
+groups.
diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst
index 37f2b42..429be72 100644
--- a/Help/command/execute_process.rst
+++ b/Help/command/execute_process.rst
@@ -22,6 +22,8 @@
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE]
[ENCODING <name>]
+ [ENVIRONMENT <variable=value>...]
+ [ENVIRONMENT_MODIFICATION <env-mod-op>...]
[ECHO_OUTPUT_VARIABLE]
[ECHO_ERROR_VARIABLE]
[COMMAND_ERROR_IS_FATAL <ANY|LAST|NONE>])
@@ -187,6 +189,27 @@
`UTF-8 RFC <https://datatracker.ietf.org/doc/html/rfc3629>`_
naming convention.
+``ENVIRONMENT <variable=value>...``
+ .. versionadded:: 4.4
+
+ Add environment variable definitions to the environment of the child
+ processes. Each entry must be of the form ``NAME=value`` and is interpreted
+ as setting ``NAME`` to ``value`` for the duration of the
+ ``execute_process()`` call.
+
+ These entries are processed in order. If the same variable name is given
+ multiple times, the last value wins.
+
+``ENVIRONMENT_MODIFICATION <env-mod-op>...``
+ .. versionadded:: 4.4
+
+ Apply one or more :prop_test:`ENVIRONMENT_MODIFICATION` operations to the
+ environment of the child processes. Each operation is applied in the given
+ order, and failures to parse an operation are treated as errors.
+
+ Environment modifications are applied after ``ENVIRONMENT`` entries, if both
+ options are specified.
+
``COMMAND_ERROR_IS_FATAL <ANY|LAST|NONE>``
.. versionadded:: 3.19
diff --git a/Help/command/file.rst b/Help/command/file.rst
index d70639d..f1e8185 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -915,6 +915,7 @@
[FORMAT <format>]
[COMPRESSION <compression>
[COMPRESSION_LEVEL <compression-level>]]
+ [ENCODING <encoding>]
[MTIME <mtime>]
[THREADS <number>]
[WORKING_DIRECTORY <dir>]
@@ -1006,6 +1007,39 @@
formats too. The ``Zstd`` algorithm compression level can be set
between 0-19, except for ``zip`` format.
+ ``ENCODING <encoding>``
+ .. versionadded:: 4.4
+
+ Specify the pathname character encoding used in the archive.
+
+ The ``<encoding>`` may be one of:
+
+ ``UTF-8``
+ Archive pathnames are encoded as UTF-8.
+
+ In CMake 4.4 and below, this is the default.
+ See policy :policy:`CMP0213` for CMake 4.3 and below compatibility
+ details.
+
+ ``OEM``
+ On Windows platforms, pathnames are encoded as using the original
+ equipment manufacturer (OEM) code page. On non-Windows platforms,
+ pathnames are encoded according to the current locale.
+
+ In CMake 4.3 and below, the ``OEM`` encoding (current locale)
+ was always used.
+
+ ``UTF-16LE``, ``UTF-16BE``
+ Archive pathnames are encoded as UTF-16 little-endian or big-endian.
+
+ ``...``
+ Any encoding name supported by ``iconv`` on the current platform.
+ On Windows, code page names may be specified.
+
+ .. note::
+ ``7zip`` archives always encode paths as ``UTF-16LE``,
+ so this option is silently ignored for that format.
+
``MTIME <mtime>``
Specify the modification time recorded in tarball entries.
@@ -1032,6 +1066,7 @@
file(ARCHIVE_EXTRACT
INPUT <archive>
[DESTINATION <dir>]
+ [ENCODING <encoding>]
[PATTERNS <pattern>...]
[LIST_ONLY]
[VERBOSE]
@@ -1050,6 +1085,41 @@
If ``DESTINATION`` is not given, the current binary directory will
be used.
+ ``ENCODING <encoding>``
+ .. versionadded:: 4.4
+
+ Specify the pathname character encoding used in the archive.
+
+ The ``<encoding>`` may be one of:
+
+ ``UTF-8``
+ Archive pathnames are encoded as UTF-8.
+
+ In CMake 4.3 and below, this is the default
+ if the :policy:`CMP0213` is ``NEW``.
+
+ ``OEM``
+ On Windows platforms, pathnames are encoded as using the original
+ equipment manufacturer (OEM) code page. On non-Windows platforms,
+ pathnames are encoded according to the current locale.
+
+ In CMake 4.3 and below, the ``OEM`` encoding (current locale)
+ was always used.
+
+ In CMake 4.4 and above, the ``OEM`` encoding (current locale)
+ is only used if the :policy:`CMP0213` is not ``NEW``.
+
+ ``UTF-16LE``, ``UTF-16BE``
+ Archive pathnames are encoded as UTF-16 little-endian or big-endian.
+
+ ``...``
+ Any encoding name supported by ``iconv`` on the current platform.
+ On Windows, code page names may be specified.
+
+ .. note::
+ ``7zip`` archives always encode paths as ``UTF-16LE``,
+ so this option is silently ignored for that format.
+
``PATTERNS <pattern>...``
Extract/list only files and directories that match one of the given
patterns. Wildcards are supported. If the ``PATTERNS`` option is
diff --git a/Help/command/if.rst b/Help/command/if.rst
index c12ec12..6433e45 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -41,19 +41,21 @@
1. `Parentheses`_.
-2. Unary tests such as `COMMAND`_, `POLICY`_, `TARGET`_, `TEST`_,
- `EXISTS`_, `IS_READABLE`_, `IS_WRITABLE`_, `IS_EXECUTABLE`_,
- `IS_DIRECTORY`_, `IS_SYMLINK`_, `IS_ABSOLUTE`_, and `DEFINED`_.
+2. Unary tests such as:
-3. Binary tests such as `EQUAL`_, `LESS`_, `LESS_EQUAL`_, `GREATER`_,
- `GREATER_EQUAL`_, `STREQUAL`_, `STRLESS`_, `STRLESS_EQUAL`_,
- `STRGREATER`_, `STRGREATER_EQUAL`_, `VERSION_EQUAL`_, `VERSION_LESS`_,
- `VERSION_LESS_EQUAL`_, `VERSION_GREATER`_, `VERSION_GREATER_EQUAL`_,
- `PATH_EQUAL`_, `IN_LIST`_, `IS_NEWER_THAN`_, and `MATCHES`_.
+ * The `Existence Checks`_ :cref:`COMMAND`, :cref:`POLICY`, :cref:`TARGET`,
+ :cref:`TEST`, :cref:`EXISTS`, and :cref:`DEFINED`.
+ * The `File Operations`_ :cref:`IS_READABLE`, :cref:`IS_WRITABLE`,
+ :cref:`IS_EXECUTABLE`, :cref:`IS_DIRECTORY`, :cref:`IS_SYMLINK`, and
+ :cref:`IS_ABSOLUTE`.
-4. Unary logical operator `NOT`_.
+3. Binary tests such as those described in `Comparisons`_,
+ `Version Comparisons`_, and `Path Comparisons`_, as well as :cref:`IN_LIST`
+ and :cref:`IS_NEWER_THAN`.
-5. Binary logical operators `AND`_ and `OR`_, from left to right,
+4. Unary logical operator :cref:`NOT`.
+
+5. Binary logical operators :cref:`AND` and :cref:`OR`, from left to right,
without any short-circuit.
Basic Expressions
@@ -181,7 +183,7 @@
False if the given path is an empty string.
.. note::
- Prefer ``if(IS_READABLE)`` to check file readability. ``if(EXISTS)``
+ Prefer :command:`if(IS_READABLE)` to check file readability. ``if(EXISTS)``
may be changed in the future to only check file existence.
.. signature:: if(IS_READABLE <path-to-file-or-directory>)
@@ -228,7 +230,7 @@
time stamps are exactly the same, an ``IS_NEWER_THAN`` comparison returns
true, so that any dependent build operations will occur in the event
of a tie. This includes the case of passing the same file name for
- both file1 and file2.
+ both ``file1`` and ``file2``.
.. signature:: if(IS_DIRECTORY <path>)
@@ -262,10 +264,8 @@
:target: MATCHES
True if the given string or variable's value matches the given regular
- expression. See :ref:`Regex Specification` for regex format.
-
- .. versionadded:: 2.6
- ``()`` groups are captured in :variable:`CMAKE_MATCH_<n>` variables.
+ expression. See :ref:`Regex Specification` for regex format. ``()`` groups
+ are captured in :variable:`CMAKE_MATCH_<n>` variables.
.. signature:: if(<variable|string> LESS <variable|string>)
:target: LESS
@@ -415,7 +415,7 @@
...
endif()
- See :ref:`cmake_path(COMPARE) <Path Comparison>` for more details.
+ See :command:`cmake_path(COMPARE)` for more details.
Variable Expansion
^^^^^^^^^^^^^^^^^^
@@ -452,40 +452,40 @@
Automatic evaluation applies in the other cases whenever the
above-documented condition syntax accepts ``<variable|string>``:
-* The left hand argument to `MATCHES`_ is first checked to see if it is
+* The left hand argument to :cref:`MATCHES` is first checked to see if it is
a defined variable. If so, the variable's value is used, otherwise the
original value is used.
-* If the left hand argument to `MATCHES`_ is missing it returns false
+* If the left hand argument to :cref:`MATCHES` is missing it returns false
without error
-* Both left and right hand arguments to `LESS`_, `GREATER`_, `EQUAL`_,
- `LESS_EQUAL`_, and `GREATER_EQUAL`_, are independently tested to see if
- they are defined variables. If so, their defined values are used otherwise
- the original value is used.
+* Both left and right hand arguments to :cref:`LESS`, :cref:`GREATER`,
+ :cref:`EQUAL`, :cref:`LESS_EQUAL`, and :cref:`GREATER_EQUAL` are
+ independently tested to see if they are defined variables. If so, their
+ defined values are used; otherwise the original value is used.
-* Both left and right hand arguments to `STRLESS`_, `STRGREATER`_,
- `STREQUAL`_, `STRLESS_EQUAL`_, and `STRGREATER_EQUAL`_ are independently
- tested to see if they are defined variables. If so, their defined values are
- used otherwise the original value is used.
+* Both left and right hand arguments to :cref:`STRLESS`, :cref:`STRGREATER`,
+ :cref:`STREQUAL`, :cref:`STRLESS_EQUAL`, and :cref:`STRGREATER_EQUAL` are
+ independently tested to see if they are defined variables. If so, their
+ defined values are used; otherwise the original value is used.
-* Both left and right hand arguments to `VERSION_LESS`_,
- `VERSION_GREATER`_, `VERSION_EQUAL`_, `VERSION_LESS_EQUAL`_, and
- `VERSION_GREATER_EQUAL`_ are independently tested to see if they are defined
- variables. If so, their defined values are used otherwise the original value
- is used.
+* Both left and right hand arguments to :cref:`VERSION_LESS`,
+ :cref:`VERSION_GREATER`, :cref:`VERSION_EQUAL`, :cref:`VERSION_LESS_EQUAL`,
+ and :cref:`VERSION_GREATER_EQUAL` are independently tested to see if they are
+ defined variables. If so, their defined values are used; otherwise the
+ original value is used.
-* The left hand argument to `IN_LIST`_ is tested to see if it is a defined
- variable. If so, the variable's value is used, otherwise the original
+* The left hand argument to :cref:`IN_LIST` is tested to see if it is a defined
+ variable. If so, the variable's value is used; otherwise the original
value is used.
-* The right hand argument to `NOT`_ is tested to see if it is a boolean
- constant. If so, the value is used, otherwise it is assumed to be a
+* The right hand argument to :cref:`NOT` is tested to see if it is a boolean
+ constant. If so, the value is used; otherwise it is assumed to be a
variable and it is dereferenced.
-* The left and right hand arguments to `AND`_ and `OR`_ are independently
- tested to see if they are boolean constants. If so, they are used as
- such, otherwise they are assumed to be variables and are dereferenced.
+* The left and right hand arguments to :cref:`AND` and :cref:`OR` are
+ independently tested to see if they are boolean constants. If so, they are
+ used as such, otherwise they are assumed to be variables and are dereferenced.
.. versionchanged:: 3.1
To prevent ambiguity, potential variable or keyword names can be
diff --git a/Help/command/include.rst b/Help/command/include.rst
index 80968da..9e87db0 100644
--- a/Help/command/include.rst
+++ b/Help/command/include.rst
@@ -6,7 +6,7 @@
.. code-block:: cmake
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>]
- [NO_POLICY_SCOPE])
+ [NO_POLICY_SCOPE] [NO_DIAGNOSTIC_SCOPE])
Loads and runs CMake code from the file given. Variable reads and
writes access the scope of the caller (dynamic scoping). If ``OPTIONAL``
@@ -23,3 +23,6 @@
See the :command:`cmake_policy` command documentation for discussion of the
``NO_POLICY_SCOPE`` option.
+
+See the :command:`cmake_diagnostic` command documentation for discussion of the
+``NO_DIAGNOSTIC_SCOPE`` option.
diff --git a/Help/command/install.rst b/Help/command/install.rst
index f7fcb94..7ed27e7 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -201,6 +201,8 @@
- DLLs (these go to ``RUNTIME``, see below),
- on macOS when marked as ``FRAMEWORK`` (see below).
+ * *Module libraries*
+
``RUNTIME``
Target artifacts of this kind include:
@@ -243,7 +245,10 @@
File sets are defined by the :command:`target_sources(FILE_SET)` command.
If the file set ``<set-name>`` exists and is ``PUBLIC`` or ``INTERFACE``,
- any files in the set are installed under the destination (see below).
+ any files in the set of type ``HEADERS`` are installed under
+ the destination (see below). Other types do not have any default
+ destination, so ``DESTINATION`` option must be specified for each
+ ``FILE_SET``.
The directory structure relative to the file set's base directories is
preserved. For example, a file added to the file set as
``/blah/include/myproj/here.h`` with a base directory ``/blah/include``
@@ -263,12 +268,13 @@
``DESTINATION`` is omitted, a default destination will be taken from the
appropriate variable from :module:`GNUInstallDirs`, or set to a built-in
default value if that variable is not defined. The same is true for file
- sets, and the public and private headers associated with the installed
- targets through the :prop_tgt:`PUBLIC_HEADER` and :prop_tgt:`PRIVATE_HEADER`
- target properties. A destination must always be provided for module libraries,
- Apple bundles and frameworks. A destination can be omitted for interface and
- object libraries, but they are handled differently (see the discussion of this
- topic toward the end of this section).
+ sets of type ``HEADERS``, and the public and private headers associated with
+ the installed targets through the :prop_tgt:`PUBLIC_HEADER` and
+ :prop_tgt:`PRIVATE_HEADER` target properties. A destination must always be
+ provided for module libraries, Apple bundles and frameworks. A destination
+ can be omitted for interface and object libraries, but they are handled
+ differently (see the discussion of this topic toward the end of this
+ section).
For shared libraries on DLL platforms, if neither ``RUNTIME`` nor ``ARCHIVE``
destinations are specified, both the ``RUNTIME`` and ``ARCHIVE`` components are
diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index 5fa4ef1..374d828 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -77,12 +77,30 @@
Adds a file set to a target, or adds files to an existing file set. Targets
have zero or more named file sets. Each file set has a name, a type, a scope of
``INTERFACE``, ``PUBLIC``, or ``PRIVATE``, one or more base directories, and
-files within those directories. The acceptable types include:
+files within those directories.
+
+.. versionchanged:: 4.4
+ A file may only belong to at most one file set in a target. See policy
+ :policy:`CMP0211`.
+
+ The acceptable types include:
``HEADERS``
Sources intended to be used via a language's ``#include`` mechanism.
+``SOURCES``
+ .. versionadded:: 4.4
+
+ Specifies sources to use when building a target and/or its dependents.
+ With the scope ``PRIVATE`` and ``PUBLIC``, items will populate the
+ :prop_fs:`SOURCES` property of ``<set>``, which are used when building the
+ target itself. With the scope ``PUBLIC`` and ``INTERFACE``, items will
+ populate the :prop_fs:`INTERFACE_SOURCES` property of ``<set>``, which are
+ used when building dependents. The sources specified by the
+ :prop_fs:`INTERFACE_SOURCES` property are propagated, transitively, to all
+ the dependents.
+
``CXX_MODULES``
.. versionadded:: 3.28
@@ -91,7 +109,8 @@
``INTERFACE`` scope except on ``IMPORTED`` targets.
The optional default file sets are named after their type. The target may not
-be a custom target or :prop_tgt:`FRAMEWORK` target.
+be a custom target or, for ``HEADERS`` and ``CXX_MODULES`` types, a
+:prop_tgt:`FRAMEWORK` target.
Files in a ``PRIVATE`` or ``PUBLIC`` file set are marked as source files for
the purposes of IDE integration. Additionally, files in ``HEADERS`` file sets
@@ -100,8 +119,8 @@
:command:`install(TARGETS)` command, and exported with the
:command:`install(EXPORT)` and :command:`export` commands.
-Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, or
-``PRIVATE`` and accepts the following arguments:
+Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``,
+or ``PRIVATE`` and accepts the following arguments:
``FILE_SET <set>``
@@ -158,6 +177,15 @@
* :prop_tgt:`HEADER_DIRS`
* :prop_tgt:`HEADER_DIRS_<NAME>`
+For file sets of type ``SOURCES``:
+
+* :prop_tgt:`SOURCE_SETS`
+* :prop_tgt:`INTERFACE_SOURCE_SETS`
+* :prop_tgt:`SOURCE_SET`
+* :prop_tgt:`SOURCE_SET_<NAME>`
+* :prop_tgt:`SOURCE_DIRS`
+* :prop_tgt:`SOURCE_DIRS_<NAME>`
+
For file sets of type ``CXX_MODULES``:
* :prop_tgt:`CXX_MODULE_SETS`
diff --git a/Help/cpack_gen/archive.rst b/Help/cpack_gen/archive.rst
index 21e67ce..3560bed 100644
--- a/Help/cpack_gen/archive.rst
+++ b/Help/cpack_gen/archive.rst
@@ -217,3 +217,18 @@
It is selected automatically by the archive library backend and
not directly set by CMake itself. The default compression level
may vary between archive formats, platforms, etc.
+
+.. variable:: CPACK_ARCHIVE_ENCODING
+
+ .. versionadded:: 4.4
+
+ Specify the pathname character encoding used in package archives.
+
+ :Default: ``UTF-8``
+
+ See the :option:`cmake -E tar <cmake-E tar>` tool's
+ :option:`--cmake-tar-encoding <cmake-E_tar --cmake-tar-encoding>` flag
+ for supported encoding names.
+
+ In CMake 4.3 and below, the ``OEM`` encoding (current locale)
+ was always used.
diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst
index 53b1e9b..a6bc84a 100644
--- a/Help/cpack_gen/nsis.rst
+++ b/Help/cpack_gen/nsis.rst
@@ -249,3 +249,9 @@
allowing an install.
Allowed values for this variable are ``on``, ``off``, and ``force``.
If not specified, the default behavior is ``on``.
+
+.. variable:: CPACK_NSIS_IGNORE_COMPONENTS_PAGE
+
+ .. versionadded:: 4.4
+
+ If set, do not display the page containing the license during installation.
diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst
index b25b822..a30b481 100644
--- a/Help/cpack_gen/rpm.rst
+++ b/Help/cpack_gen/rpm.rst
@@ -553,6 +553,10 @@
set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
+ .. versionadded:: 4.4
+ If the variable is a list, its string elements will be concatenated using
+ ``\n`` before being substituted into the spec template.
+
.. variable:: CPACK_RPM_PACKAGE_DEBUG
Toggle CPack RPM generator debug output.
diff --git a/Help/dev/ai-policy.rst b/Help/dev/ai-policy.rst
new file mode 100644
index 0000000..b18a5cd
--- /dev/null
+++ b/Help/dev/ai-policy.rst
@@ -0,0 +1,18 @@
+AI Policy
+*********
+
+The CMake project supports the responsible use of AI services and tools.
+Contributors are welcome to use AI tools and services to help them be more
+effective, subject to the following guidelines:
+
+* A human author must be responsible for any submission to the CMake project's
+ GitLab instance or forums. This includes merge requests, issues, and forum
+ posts. AI tools and services must not make submissions or comments without
+ a human author being associated with and responsible for them.
+
+* All merge request submissions are expected to be fully understood by the
+ contributing author.
+
+* AI tools and services are not considered authors. They should not be listed
+ as co-authors, and their review is not considered adequate for demonstrating
+ a human author's understanding or the correctness of a proposed change.
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
index 3d52871..30d53ff 100644
--- a/Help/dev/experimental.rst
+++ b/Help/dev/experimental.rst
@@ -127,7 +127,7 @@
In order to activate support for Rust, set
* variable ``CMAKE_EXPERIMENTAL_RUST`` to
-* value ``3cc9b32c-47d3-4056-8953-d74e69fc0d6c``.
+* value ``efaed83b-d73a-48af-999a-bd0a6172c313``.
This UUID may change in future versions of CMake. Be sure to use the value
documented here by the source tree of the version of CMake with which you are
diff --git a/Help/dev/source.rst b/Help/dev/source.rst
index 3aad194..ec4e12c 100644
--- a/Help/dev/source.rst
+++ b/Help/dev/source.rst
@@ -209,6 +209,9 @@
* ``<cm/map>`` :
``cm::erase_if``, ``cm::ssize``
+ * ``<cm/ranges>``:
+ ``cm::ranges::views::keys``, ``cm::ranges::views::values``
+
* ``<cm/set>`` :
``cm::erase_if``, ``cm::ssize``
@@ -244,6 +247,14 @@
* ``cm::contains``:
Checks if element or key is contained in container.
+ * ``cm::keys``
+ Extract keys from associative container or sequence container with tuple as
+ element
+
+ * ``cm::values``
+ Extract values from associative container or sequence container with tuple as
+ element
+
* ``<cmext/enum_set>``
* ``cm::enum_set``:
@@ -275,6 +286,12 @@
* ``<cmext/type_traits>``:
+ * ``cm::is_pair``:
+ Checks if a type is a std::pair<> type.
+
+ * ``cm::is_tuple``:
+ Checks if a type is a std::tuple<> type.
+
* ``cm::is_container``:
Checks if a type is a container type.
diff --git a/Help/envvar/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst b/Help/envvar/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst
new file mode 100644
index 0000000..0a8723e
--- /dev/null
+++ b/Help/envvar/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst
@@ -0,0 +1,11 @@
+CMAKE_DISABLE_PRECOMPILE_HEADERS
+--------------------------------
+
+.. versionadded:: 4.4
+
+.. include:: include/ENV_VAR.rst
+
+The default value for the :variable:`CMAKE_DISABLE_PRECOMPILE_HEADERS` variable
+when there is no explicit configuration given on the first run while creating a
+new build tree. On later runs in an existing build tree the value persists in
+the cache as :variable:`CMAKE_DISABLE_PRECOMPILE_HEADERS`.
diff --git a/Help/guide/user-interaction/index.rst b/Help/guide/user-interaction/index.rst
index fe8a45a..f11b23d 100644
--- a/Help/guide/user-interaction/index.rst
+++ b/Help/guide/user-interaction/index.rst
@@ -71,7 +71,7 @@
for the provider of the software, not intended for the
consumer of the software. Such warnings end with "This
warning is for project developers". Users may disable
-such warnings by passing the :option:`-Wno-dev <cmake -Wno-dev>`
+such warnings by passing the :option:`-Wno-author <cmake -Wno->`
flag to :manual:`cmake(1)`.
cmake-gui tool
diff --git a/Help/index.rst b/Help/index.rst
index f9ffcba..fa7d199 100644
--- a/Help/index.rst
+++ b/Help/index.rst
@@ -60,6 +60,7 @@
/manual/cmake-configure-log.7
/manual/cmake-cxxmodules.7
/manual/cmake-developer.7
+ /manual/cmake-diagnostics.7
/manual/cmake-env-variables.7
/manual/cmake-file-api.7
/manual/cmake-generator-expressions.7
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index 6f1a947..8a25b62 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -17,6 +17,7 @@
/command/block
/command/break
+ /command/cmake_diagnostic
/command/cmake_host_system_information
/command/cmake_language
/command/cmake_minimum_required
@@ -93,6 +94,7 @@
/command/cmake_instrumentation
/command/create_test_sourcelist
/command/define_property
+ /command/discover_tests
/command/enable_language
/command/enable_testing
/command/export
diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst
index 9dc14d2..c9f9521 100644
--- a/Help/manual/cmake-cxxmodules.7.rst
+++ b/Help/manual/cmake-cxxmodules.7.rst
@@ -50,8 +50,11 @@
be scanned.
- If the target does not use at least C++ 20, it will not be scanned.
- If the source file is not the language ``CXX``, it will not be scanned.
-- If the :prop_sf:`CXX_SCAN_FOR_MODULES` source file property is set, its
+- If the source file belongs to a file set that is not of type ``CXX_MODULES``,
+ and the :prop_fs:`CXX_SCAN_FOR_MODULES` file set property is set, its
value will be used.
+- If the :prop_sf:`CXX_SCAN_FOR_MODULES` source file property is set in the
+ target's directory, its value will be used.
- If the :prop_tgt:`CXX_SCAN_FOR_MODULES` target property is set, its value
will be used. Set the :variable:`CMAKE_CXX_SCAN_FOR_MODULES` variable
to initialize this property on all targets as they are created.
@@ -69,7 +72,13 @@
modules includes:
* MSVC toolset 14.34 and newer (provided with Visual Studio 17.4 and newer)
+
* LLVM/Clang 16.0 and newer
+
+ .. versionadded:: 4.4
+
+ ``clang-cl`` version 19.1 and newer
+
* GCC 14 and newer
``import std`` Support
diff --git a/Help/manual/cmake-diagnostics.7.rst b/Help/manual/cmake-diagnostics.7.rst
new file mode 100644
index 0000000..66a08d5
--- /dev/null
+++ b/Help/manual/cmake-diagnostics.7.rst
@@ -0,0 +1,90 @@
+.. cmake-manual-description: CMake Diagnostics Reference
+
+cmake-diagnostics(7)
+********************
+
+.. only:: html
+
+ .. contents::
+
+.. _cmake-diagnostics-intro:
+
+Introduction
+============
+
+.. versionadded:: 4.4
+
+CMake Diagnostics are the mechanism by which CMake categorizes and presents
+certain advisory information about a project's configuration and the generation
+of its build system. These diagnostics can be seen as the build system
+equivalent of compiler warnings. Diagnostics provide feedback on potential
+issues in several categories:
+
+* Issues that may impact the success of the build.
+
+* Issues that may impact the correctness of the build.
+
+* Issues that may impact the correctness of the project packaging.
+
+* Issues that may impact the ability of the project
+ to be built with newer versions of dependencies.
+
+* Issues that may impact the ability of the project
+ to be built with newer versions of CMake.
+
+Diagnostic Actions
+------------------
+
+The action taken when a particular diagnostic is triggered depends on the
+diagnostic category. Most categories will warn by default. The
+:command:`cmake_diagnostic` command and :option:`-W <cmake -W>` options can be
+used to control what action occurs when a diagnostic of a particular category
+is triggered. The possible actions are described in the documentation of the
+same.
+
+Diagnostic Categories
+=====================
+
+The following categories are defined.
+
+``CMD_AUTHOR`` (``-Wauthor``)
+-----------------------------
+
+:Default: Warn
+
+Warn about a build system's incorrect use of CMake, or of a CMake interface
+provided by a dependency. This is the category triggered by
+:command:`message(AUTHOR_WARNING)`. It is also the ancestor of many other
+diagnostic categories.
+
+The most important aspect of this category is that it represents issues with
+a project's build system which typically require alteration to the same. This
+is to say that users simply trying to build a project obtained elsewhere will
+typically not be interested in these warnings, except to perhaps report them
+to the project's developer(s).
+
+``CMD_DEPRECATED`` (``-Wdeprecated``)
+-------------------------------------
+
+:Default: Warn
+:Parent: ``CMD_AUTHOR``
+
+Warn about use of a deprecated function or package. This is the category
+triggered by :command:`message(DEPRECATION)`.
+
+``CMD_UNINITIALIZED`` (``-Wuninitialized``)
+-------------------------------------------
+
+:Default: Ignore
+
+Warn if an uninitialized variable is dereferenced.
+
+``CMD_UNUSED_CLI`` (``-Wunused-cli``)
+-------------------------------------
+
+:Default: Warn
+
+Warn about variables that are declared on the command line, but not used.
+
+Although the action of this warning category can be queried as usual, changes
+made using the :command:`cmake_diagnostic` command have no effect.
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index f1b1cb1..e3779c0 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -52,6 +52,7 @@
/envvar/CMAKE_CONFIG_TYPE
/envvar/CMAKE_CONFIGURATION_TYPES
/envvar/CMAKE_CROSSCOMPILING_EMULATOR
+ /envvar/CMAKE_DISABLE_PRECOMPILE_HEADERS
/envvar/CMAKE_EXPORT_BUILD_DATABASE
/envvar/CMAKE_EXPORT_COMPILE_COMMANDS
/envvar/CMAKE_FASTBUILD_VERBOSE_GENERATOR
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index ac25627..51ed27e 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -43,6 +43,12 @@
:variable:`CMAKE_CXX_COMPILER_VERSION <CMAKE_<LANG>_COMPILER_VERSION>` is less
than 4.2.0.
+.. note::
+
+ Generator expressions are supported in the values of many properties,
+ but not all. Check a property's documentation for explicit mention
+ of generator expressions before using them.
+
Whitespace And Quoting
======================
@@ -3298,13 +3304,23 @@
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-.. genex:: $<TARGET_OBJECTS:tgt>
+.. genex:: $<TARGET_OBJECTS:tgt[,SOURCE_FILES:source_file[;source_file]...]>
.. versionadded:: 3.1
List of objects resulting from building ``tgt``. This would typically be
used on :ref:`object library <Object Libraries>` targets.
+ Additional arguments:
+
+ ``SOURCE_FILES:source_file[;source_file]...``
+
+ .. versionadded:: 4.4
+
+ An optional list of one or more source files for the target. Only the
+ object files built from those source files will be returned (but not
+ necessarily in the same order they were specified).
+
.. genex:: $<TARGET_RUNTIME_DLLS:tgt>
.. versionadded:: 3.21
diff --git a/Help/manual/cmake-instrumentation.7.rst b/Help/manual/cmake-instrumentation.7.rst
index 582adf8..9fe2d3c 100644
--- a/Help/manual/cmake-instrumentation.7.rst
+++ b/Help/manual/cmake-instrumentation.7.rst
@@ -606,6 +606,10 @@
"trace": "trace/trace-<timestamp>.json"
}
+.. versionadded:: 4.4
+ The JSON format is described in machine-readable form by
+ :download:`this JSON schema </manual/instrumentation/index-v1-schema.json>`.
+
.. _`cmake-instrumentation v1 CMake Content File`:
v1 CMake Content File
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index c6bdacb..b8f120c 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -36,10 +36,10 @@
.. code-block:: cmake
- cmake_minimum_required(VERSION 3.10...4.2)
+ cmake_minimum_required(VERSION 3.10...4.3)
This uses the ``<min>...<policy_max>`` syntax to enable the ``NEW`` behaviors
-of policies introduced in CMake 4.2 and earlier while only requiring a
+of policies introduced in CMake 4.3 and earlier while only requiring a
minimum version of CMake 3.10. The project is expected to work with
both the ``OLD`` and ``NEW`` behaviors of policies introduced between
those versions.
@@ -94,6 +94,16 @@
The following policies are supported.
+Policies Introduced by CMake 4.4
+--------------------------------
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0213: file(ARCHIVE_{CREATE,EXTRACT}) encode archive paths as UTF-8 by default. </policy/CMP0213>
+ CMP0212: add_custom_command DEPENDS does not strip .exe suffixes. </policy/CMP0212>
+ CMP0211: A file may belong to at most one file set in a target. </policy/CMP0211>
+
Policies Introduced by CMake 4.3
--------------------------------
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index 8bbee0f..e135cdf 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -21,7 +21,7 @@
``CMakePresets.json`` and ``CMakeUserPresets.json`` live in the project's root
directory. They both have exactly the same format, and both are optional
-(though at least one must be present if :option:`--preset <cmake --preset>`
+(though at least one must be present if :cmake-option:`--preset`
is specified). ``CMakePresets.json`` is meant to specify project-wide build
details, while ``CMakeUserPresets.json`` is meant for developers to specify
their own local build details.
@@ -39,72 +39,14 @@
.. literalinclude:: presets/example.json
:language: json
-Preset files specifying version ``10`` or above may include comments using the
-key ``$comment`` at any level within the JSON object to provide documentation.
+.. presets-versionadded:: 10
+
+ Preset files may include comments using the key ``$comment`` at any level
+ within the JSON object to provide documentation.
The root object recognizes the following fields:
-.. _`CMakePresets schema`:
-
-``$schema``
- An optional string that provides a URI to the JSON schema that describes the
- structure of this JSON document. This field is used for validation and
- autocompletion in editors that support JSON schema. It doesn't affect the
- behavior of the document itself. If this field is not specified, the JSON
- document will still be valid, but tools that use JSON schema for validation
- and autocompletion may not function correctly.
-
-``version``
- A required integer representing the version of the JSON schema. See
- `Versions`_ for discussion of the supported versions and the corresponding
- version of CMake in which they were added.
-
-``cmakeMinimumRequired``
- An optional object representing the minimum version of CMake needed to
- build this project. This object consists of the following fields:
-
- ``major``
- An optional integer representing the major version.
-
- ``minor``
- An optional integer representing the minor version.
-
- ``patch``
- An optional integer representing the patch version.
-
-``include``
- An optional array of strings representing files to include. If the filenames
- are not absolute, they are considered relative to the current file.
- This is allowed in preset files specifying version ``4`` or above.
- See `Includes`_ for discussion of the constraints on included files.
-
-``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, the keys should be a vendor-specific domain name
- followed by a ``/``-separated path. For example, the Example IDE 1.0 could
- use ``example.com/ExampleIDE/1.0``. The value of each field can be anything
- desired by the vendor, though will typically be a map.
-
-``configurePresets``
- An optional array of `Configure Preset`_ objects.
- This is allowed in preset files specifying version ``1`` or above.
-
-``buildPresets``
- An optional array of `Build Preset`_ objects.
- This is allowed in preset files specifying version ``2`` or above.
-
-``testPresets``
- An optional array of `Test Preset`_ objects.
- This is allowed in preset files specifying version ``2`` or above.
-
-``packagePresets``
- An optional array of `Package Preset`_ objects.
- This is allowed in preset files specifying version ``6`` or above.
-
-``workflowPresets``
- An optional array of `Workflow Preset`_ objects.
- This is allowed in preset files specifying version ``6`` or above.
+.. include:: presets/root-properties.rst
Includes
^^^^^^^^
@@ -126,11 +68,18 @@
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. Starting from version
-``9``, other macro expansions are also available, except for ``$env{}`` and
-preset-specific macros, i.e., those derived from the fields inside a preset's
-definition like ``presetName``.
+.. presets-versionchanged:: 7
+
+ The ``include`` field supports `macro expansion`_, but only ``$penv{}`` macro
+ expansion.
+
+.. presets-versionchanged:: 9
+
+ The ``include`` field supports `macro expansion`_, except for ``$env{}`` and
+ preset-specific macros (i.e., those derived from the fields inside a preset's
+ definition like ``presetName``).
+
+.. _`Configure Preset`:
Configure Preset
^^^^^^^^^^^^^^^^
@@ -138,1051 +87,69 @@
Each entry of the ``configurePresets`` array is a JSON object
that may contain the following fields:
-``name``
- A required string representing the machine-friendly name of the preset.
- This identifier is used in the :option:`cmake --preset` option.
- There must not be two configure presets in the union of ``CMakePresets.json``
- and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a configure preset may have the same name as a build, test,
- package, or workflow preset.
+.. include:: presets/configurePresets-properties.rst
-``hidden``
- An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the
- :option:`--preset <cmake --preset>` argument, will not show up in the
- :manual:`CMake GUI <cmake-gui(1)>`, and does not have to have a valid
- ``generator`` or ``binaryDir``, even from inheritance. ``hidden`` presets are
- intended to be used as a base for other presets to inherit via the
- ``inherits`` field.
-
-``inherits``
- An optional array of strings representing the names of presets to inherit
- from. This field can also be a string, which is equivalent to an array
- containing one string.
-
- The preset will inherit all of the fields from the ``inherits``
- presets by default (except ``name``, ``hidden``, ``inherits``,
- ``description``, and ``displayName``), but can override them as
- desired. If multiple ``inherits`` presets provide conflicting values for
- the same field, the earlier preset in the ``inherits`` array will be
- preferred.
-
- A preset can only inherit from another preset that is defined in the
- same file or in one of the files it includes (directly or indirectly).
- Presets in ``CMakePresets.json`` may not inherit from presets in
- ``CMakeUserPresets.json``.
-
-``condition``
- An optional `Condition`_ object. This is allowed in preset files specifying
- version ``3`` or above.
-
-``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. If vendors use their own per-preset
- ``vendor`` field, they should implement inheritance in a sensible manner
- when appropriate.
-
-``displayName``
- An optional string with a human-friendly name of the preset.
-
-``description``
- An optional string with a human-friendly description of the preset.
-
-.. _`CMakePresets generator`:
-
-``generator``
- An optional string representing the :manual:`generator <cmake-generators(7)>`
- to use for the preset. If ``generator`` is not specified, it must be
- inherited from the ``inherits`` preset (unless this preset is ``hidden``).
- In version ``3`` or above, this field may be omitted to fall back to regular
- generator discovery procedure.
-
- Note that for :ref:`Visual Studio generators`, unlike in the command line
- :option:`-G <cmake -G>` argument, you cannot include the platform name
- in the generator name. Use the ``architecture`` field instead.
-
-``architecture``, ``toolset``
- Optional fields representing the platform and toolset, respectively, for
- :manual:`generators <cmake-generators(7)>` that support them.
-
- See :option:`cmake -A` option for possible values for ``architecture``
- and :option:`cmake -T` for ``toolset``.
-
- Each may be either a string or an object with the following fields:
-
- ``value``
- An optional string representing the value.
-
- ``strategy``
- An optional string telling CMake how to handle the ``architecture`` or
- ``toolset`` field. Valid values are:
-
- ``"set"``
- Set the respective value. This will result in an error for generators
- that do not support the respective field.
-
- ``"external"``
- Do not set the value, even if the generator supports it. This is
- useful if, for example, a preset uses the Ninja generator, and an IDE
- knows how to set up the Visual C++ environment from the
- ``architecture`` and ``toolset`` fields. In that case, CMake will
- ignore the field, but the IDE can use them to set up the environment
- before invoking CMake.
-
- If no ``strategy`` field is given, or if the field uses the string form
- rather than the object form, the behavior is the same as ``"set"``.
-
-.. _`CMakePresets toolchainFile`:
-
-``toolchainFile``
- An optional string representing the path to the toolchain file.
- This field supports `macro expansion`_. If a relative path is specified,
- it is calculated relative to the build directory, and if not found,
- relative to the source directory. This field takes precedence over any
- :variable:`CMAKE_TOOLCHAIN_FILE` value. It is allowed in preset files
- specifying version ``3`` or above.
-
-.. _`CMakePresets graphviz`:
-
-``graphviz``
- An optional string representing the path to the graphviz input file,
- that will contain all the library and executable dependencies
- in the project. See the documentation for :option:`cmake --graphviz` for
- more details.
-
- This field supports `macro expansion`_. If a relative path is specified,
- it is calculated relative to the current working directory. It is allowed
- in preset files specifying version ``10`` or above.
-
-.. _`CMakePresets binaryDir`:
-
-``binaryDir``
- An optional string representing the path to the output binary directory.
- This field supports `macro expansion`_. If a relative path is specified,
- it is calculated relative to the source directory. If ``binaryDir`` is not
- specified, it must be inherited from the ``inherits`` preset (unless this
- preset is ``hidden``). In version ``3`` or above, this field may be
- omitted.
-
-.. _`CMakePresets installDir`:
-
-``installDir``
- An optional string representing the path to the installation directory,
- which will be used as the :variable:`CMAKE_INSTALL_PREFIX` variable.
- This field supports `macro expansion`_. If a relative path is specified,
- it is calculated relative to the source directory. This is allowed in
- preset files specifying version ``3`` or above.
-
-``cmakeExecutable``
- An optional string representing the path to the CMake executable to use
- for this preset. This is reserved for use by IDEs, and is not used by
- CMake itself. IDEs that use this field should expand any macros in it.
-
-``cacheVariables``
- An optional map of cache variables. The key is the variable name (which
- may not be an empty string), and the value is either ``null``, a boolean
- (which is equivalent to a value of ``"TRUE"`` or ``"FALSE"`` and a type
- of ``BOOL``), a string representing the value of the variable (which
- supports `macro expansion`_), or an object with the following fields:
-
- ``type``
- An optional string representing the type of the variable.
-
- ``value``
- A required string or boolean representing the value of the variable.
- A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``. This field
- supports `macro expansion`_.
-
- Cache variables are inherited through the ``inherits`` field, and the
- preset's variables will be the union of its own ``cacheVariables`` and
- the ``cacheVariables`` from all its parents. If multiple presets in this
- union define the same variable, the standard rules of ``inherits`` are
- applied. Setting a variable to ``null`` causes it to not be set, even if
- a value was inherited from another preset.
-
-``environment``
- An optional map of environment variables. The key is the variable name
- (which may not be an empty string), and the value is either ``null`` or
- a string representing the value of the variable. Each variable is set
- regardless of whether or not a value was given to it by the process's
- environment.
-
- This field supports `macro expansion`_, and environment variables in this map
- may reference each other, and may be listed in any order, as long as such
- references do not cause a cycle (for example, if ``ENV_1`` is
- ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
- allows one to prepend or append values to existing environment variables by
- accessing only values from the parent environment.
-
- Environment variables are inherited through the ``inherits`` field, and
- the preset's environment will be the union of its own ``environment`` and
- the ``environment`` from all its parents. If multiple presets in this
- union define the same variable, the standard rules of ``inherits`` are
- applied. Setting a variable to ``null`` causes it to not be set, even if
- a value was inherited from another preset.
-
-``warnings``
- An optional object specifying the warnings to enable. The object may
- contain the following fields:
-
- ``dev``
- An optional boolean. Equivalent to passing :option:`-Wdev <cmake -Wdev>`
- or :option:`-Wno-dev <cmake -Wno-dev>` on the command line. This may not
- be set to ``false`` if ``errors.dev`` is set to ``true``.
-
- ``deprecated``
- An optional boolean. Equivalent to passing
- :option:`-Wdeprecated <cmake -Wdeprecated>` or
- :option:`-Wno-deprecated <cmake -Wno-deprecated>` on the command line.
- This may not be set to ``false`` if ``errors.deprecated`` is set to
- ``true``.
-
- ``uninitialized``
- An optional boolean. Setting this to ``true`` is equivalent to passing
- :option:`--warn-uninitialized <cmake --warn-uninitialized>` on the command
- line.
-
- ``unusedCli``
- An optional boolean. Setting this to ``false`` is equivalent to passing
- :option:`--no-warn-unused-cli <cmake --no-warn-unused-cli>` on the command
- line.
-
- ``systemVars``
- An optional boolean. Setting this to ``true`` is equivalent to passing
- :option:`--check-system-vars <cmake --check-system-vars>` on the command
- line.
-
-``errors``
- An optional object specifying the errors to enable. The object may
- contain the following fields:
-
- ``dev``
- An optional boolean. Equivalent to passing :option:`-Werror=dev <cmake -Werror>`
- or :option:`-Wno-error=dev <cmake -Werror>` on the command line.
- This may not be set to ``true`` if ``warnings.dev`` is set to ``false``.
-
- ``deprecated``
- An optional boolean. Equivalent to passing
- :option:`-Werror=deprecated <cmake -Werror>` or
- :option:`-Wno-error=deprecated <cmake -Werror>` on the command line.
- This may not be set to ``true`` if ``warnings.deprecated`` is set to
- ``false``.
-
-``debug``
- An optional object specifying debug options. The object may contain the
- following fields:
-
- ``output``
- An optional boolean. Setting this to ``true`` is equivalent to passing
- :option:`--debug-output <cmake --debug-output>` on the command line.
-
- ``tryCompile``
- An optional boolean. Setting this to ``true`` is equivalent to passing
- :option:`--debug-trycompile <cmake --debug-trycompile>` on the command
- line.
-
- ``find``
- An optional boolean. Setting this to ``true`` is equivalent to passing
- :option:`--debug-find <cmake --debug-find>` on the command line.
-
-.. _`CMakePresets trace`:
-
-``trace``
- An optional object specifying trace options. This is allowed in preset
- files specifying version ``7``. The object may contain the following fields:
-
- ``mode``
- An optional string that specifies the trace mode. Valid values are:
-
- ``on``
- Causes a trace of all calls made and from where to be printed.
- Equivalent to passing :option:`--trace <cmake --trace>` on the command
- line.
-
- ``off``
- A trace of all calls will not be printed.
-
- ``expand``
- Causes a trace with variables expanded of all calls made and from where
- to be printed. Equivalent to passing :option:`--trace-expand <cmake --trace-expand>`
- on the command line.
-
- ``format``
- An optional string that specifies the format output of the trace.
- Valid values are:
-
- ``human``
- Prints each trace line in a human-readable format.
- This is the default format. Equivalent to passing
- :option:`--trace-format=human <cmake --trace-format>`
- on the command line.
-
- ``json-v1``
- Prints each line as a separate JSON document. Equivalent to passing
- :option:`--trace-format=json-v1 <cmake --trace-format>`
- on the command line.
-
- ``source``
- An optional array of strings representing the paths of source files to
- be traced. This field can also be a string, which is equivalent to an
- array containing one string. Equivalent to passing
- :option:`--trace-source <cmake --trace-source>` on the command line.
-
- ``redirect``
- An optional string specifying a path to a trace output file. Equivalent
- to passing :option:`--trace-redirect <cmake --trace-redirect>`
- on the command line.
+.. _`Build Preset`:
Build Preset
^^^^^^^^^^^^
+.. presets-versionadded:: 2
+
Each entry of the ``buildPresets`` array is a JSON object
that may contain the following fields:
-``name``
- A required string representing the machine-friendly name of the preset.
- This identifier is used in the
- :option:`cmake --build --preset <cmake--build --preset>` option.
- There must not be two build presets in the union of ``CMakePresets.json``
- and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a build preset may have the same name as a configure, test,
- package, or workflow preset.
+.. include:: presets/buildPresets-properties.rst
-``hidden``
- An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the
- :option:`--preset <cmake--build --preset>` argument
- and does not have to have a valid ``configurePreset``, even from
- inheritance. ``hidden`` presets are intended to be used as a base for
- other presets to inherit via the ``inherits`` field.
-
-``inherits``
- An optional array of strings representing the names of presets to inherit
- from. This field can also be a string, which is equivalent to an array
- containing one string.
-
- The preset will inherit all of the fields from the
- ``inherits`` presets by default (except ``name``, ``hidden``,
- ``inherits``, ``description``, and ``displayName``), but can override
- them as desired. If multiple ``inherits`` presets provide conflicting
- values for the same field, the earlier preset in the ``inherits`` array
- will be preferred.
-
- A preset can only inherit from another preset that is defined in the
- same file or in one of the files it includes (directly or indirectly).
- Presets in ``CMakePresets.json`` may not inherit from presets in
- ``CMakeUserPresets.json``.
-
-``condition``
- An optional `Condition`_ object. This is allowed in preset files specifying
- version ``3`` or above.
-
-``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. If vendors use their own per-preset
- ``vendor`` field, they should implement inheritance in a sensible manner
- when appropriate.
-
-``displayName``
- An optional string with a human-friendly name of the preset.
-
-``description``
- An optional string with a human-friendly description of the preset.
-
-.. _`CMakePresets build environment`:
-
-``environment``
- An optional map of environment variables. The key is the variable name
- (which may not be an empty string), and the value is either ``null`` or
- a string representing the value of the variable. Each variable is set
- regardless of whether or not a value was given to it by the process's
- environment.
-
- This field supports `macro expansion`_, and environment variables in this map
- may reference each other, and may be listed in any order, as long as such
- references do not cause a cycle (for example, if ``ENV_1`` is
- ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
- allows one to prepend or append values to existing environment variables by
- accessing only values from the parent environment.
-
- Environment variables are inherited through the ``inherits`` field, and
- the preset's environment will be the union of its own ``environment``
- and the ``environment`` from all its parents. If multiple presets in
- this union define the same variable, the standard rules of ``inherits``
- are applied. Setting a variable to ``null`` causes it to not be set,
- even if a value was inherited from another preset.
-
- .. note::
-
- For a CMake project using :module:`ExternalProject` with a configuration
- preset having environment variables needed in the ExternalProject, use a
- build preset that inherits that configuration preset or the ExternalProject
- will not have the environment variables set in the configuration preset.
- Example: suppose the host defaults to one compiler (say Clang)
- and the user wishes to use another compiler (say GCC). Set configuration
- preset environment variables :envvar:`CC` and :envvar:`CXX` and use a build
- preset that inherits that configuration preset. Otherwise the
- ExternalProject may use a different (system default) compiler than the
- top-level CMake project.
-
-``configurePreset``
- An optional string specifying the name of a configure preset to
- associate with this build preset. If ``configurePreset`` is not
- specified, it must be inherited from the inherits preset (unless this
- preset is hidden). The build directory is inferred from the configure
- preset, so the build will take place in the same ``binaryDir`` that the
- configuration did.
-
-``inheritConfigureEnvironment``
- An optional boolean that defaults to true. If true, the environment
- variables from the associated configure preset are inherited after all
- inherited build preset environments, but before environment variables
- explicitly specified in this build preset.
-
-.. _`CMakePresets build jobs`:
-
-``jobs``
- An optional integer. Equivalent to passing
- :option:`--parallel <cmake--build --parallel>` or ``-j`` on the command line.
- If the value is ``0``, it is equivalent to passing ``--parallel`` with
- ``<jobs>`` omitted; alternatively, one can define the environment variable
- :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` as an empty string using the
- ``environment`` field.
-
- .. versionchanged:: 4.3
-
- This field does not accept negative integer values, regardless of the
- version in the preset file.
-
-``targets``
- An optional string or array of strings. Equivalent to passing
- :option:`--target <cmake--build --target>` or ``-t`` on the command line.
- Vendors may ignore the targets property or hide build presets that
- explicitly specify targets. This field supports macro expansion.
-
-``configuration``
- An optional string. Equivalent to passing
- :option:`--config <cmake--build --config>` on the command line.
-
-``cleanFirst``
- An optional bool. If true, equivalent to passing
- :option:`--clean-first <cmake--build --clean-first>` on the command line.
-
-.. _`CMakePresets resolvePackageReferences`:
-
-``resolvePackageReferences``
- An optional string that specifies the package resolve mode. This is
- allowed in preset files specifying version ``4`` or above.
-
- Package references are used to define dependencies to packages from
- external package managers. Currently only NuGet in combination with the
- :ref:`Visual Studio generators` is supported. If there are no targets that
- define package references, this option does nothing. Valid values are:
-
- ``on``
- Causes package references to be resolved before attempting a build.
-
- ``off``
- Package references will not be resolved. Note that this may cause
- errors in some build environments, such as .NET SDK style projects.
-
- ``only``
- Only resolve package references, but do not perform a build.
-
- .. note::
-
- The command line parameter
- :option:`--resolve-package-references <cmake--build --resolve-package-references>`
- will take priority over this setting. If the command line parameter is not
- provided and this setting is not specified, an environment-specific cache
- variable will be evaluated to decide, if package restoration should be
- performed.
-
- When using the :ref:`Visual Studio generators`, package references are
- defined using the :prop_tgt:`VS_PACKAGE_REFERENCES` property. Package
- references are restored using NuGet. It can be disabled by setting the
- :variable:`CMAKE_VS_NUGET_PACKAGE_RESTORE` variable to ``OFF``. This can
- also be done from within a configure preset.
-
-``verbose``
- An optional bool. If true, equivalent to passing
- :option:`--verbose <cmake--build --verbose>` on the command line.
-
-``nativeToolOptions``
- An optional array of strings. Equivalent to passing options after ``--``
- on the command line. The array values support macro expansion.
+.. _`Test Preset`:
Test Preset
^^^^^^^^^^^
+.. presets-versionadded:: 2
+
Each entry of the ``testPresets`` array is a JSON object
that may contain the following fields:
-``name``
- A required string representing the machine-friendly name of the preset.
- This identifier is used in the :option:`ctest --preset` option.
- There must not be two test presets in the union of ``CMakePresets.json``
- and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a test preset may have the same name as a configure, build,
- package, or workflow preset.
+.. include:: presets/testPresets-properties.rst
-``hidden``
- An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the
- :option:`--preset <ctest --preset>` argument
- and does not have to have a valid ``configurePreset``, even from
- inheritance. ``hidden`` presets are intended to be used as a base for
- other presets to inherit via the ``inherits`` field.
-
-``inherits``
- An optional array of strings representing the names of presets to inherit
- from. This field can also be a string, which is equivalent to an array
- containing one string.
-
- The preset will inherit all of the fields from the
- ``inherits`` presets by default (except ``name``, ``hidden``,
- ``inherits``, ``description``, and ``displayName``), but can override
- them as desired. If multiple ``inherits`` presets provide conflicting
- values for the same field, the earlier preset in the ``inherits`` array
- will be preferred.
-
- A preset can only inherit from another preset that is defined in the
- same file or in one of the files it includes (directly or indirectly).
- Presets in ``CMakePresets.json`` may not inherit from presets in
- ``CMakeUserPresets.json``.
-
-``condition``
- An optional `Condition`_ object. This is allowed in preset files specifying
- version ``3`` or above.
-
-``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. If vendors use their own per-preset
- ``vendor`` field, they should implement inheritance in a sensible manner
- when appropriate.
-
-``displayName``
- An optional string with a human-friendly name of the preset.
-
-``description``
- An optional string with a human-friendly description of the preset.
-
-``environment``
- An optional map of environment variables. The key is the variable name
- (which may not be an empty string), and the value is either ``null`` or
- a string representing the value of the variable. Each variable is set
- regardless of whether or not a value was given to it by the process's
- environment.
-
- This field supports `macro expansion`_, and environment variables in this map
- may reference each other, and may be listed in any order, as long as such
- references do not cause a cycle (for example, if ``ENV_1`` is
- ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
- allows one to prepend or append values to existing environment variables by
- accessing only values from the parent environment.
-
- Environment variables are inherited through the ``inherits`` field, and
- the preset's environment will be the union of its own ``environment``
- and the ``environment`` from all its parents. If multiple presets in
- this union define the same variable, the standard rules of ``inherits``
- are applied. Setting a variable to ``null`` causes it to not be set,
- even if a value was inherited from another preset.
-
-``configurePreset``
- An optional string specifying the name of a configure preset to
- associate with this test preset. If ``configurePreset`` is not
- specified, it must be inherited from the inherits preset (unless this
- preset is hidden). The build directory is inferred from the configure
- preset, so tests will run in the same ``binaryDir`` that the
- configuration did and build did.
-
-``inheritConfigureEnvironment``
- An optional boolean that defaults to true. If true, the environment
- variables from the associated configure preset are inherited after all
- inherited test preset environments, but before environment variables
- explicitly specified in this test preset.
-
-``configuration``
- An optional string. Equivalent to passing
- :option:`--build-config <ctest --build-config>` on the command line.
-
-``overwriteConfigurationFile``
- An optional array of configuration options to overwrite options
- specified in the CTest configuration file. Equivalent to passing
- :option:`--overwrite <ctest --overwrite>` for each value in the array.
- The array values support macro expansion.
-
-.. _`CMakePresets output`:
-
-``output``
- An optional object specifying output options. The object may contain the
- following fields.
-
- ``shortProgress``
- An optional bool. If true, equivalent to passing
- :option:`--progress <ctest --progress>` on the command line.
-
- ``verbosity``
- An optional string specifying verbosity level. Must be one of the
- following:
-
- ``default``
- Equivalent to passing no verbosity flags on the command line.
-
- ``verbose``
- Equivalent to passing :option:`--verbose <ctest --verbose>` on
- the command line.
-
- ``extra``
- Equivalent to passing :option:`--extra-verbose <ctest --extra-verbose>`
- on the command line.
-
- ``debug``
- An optional bool. If true, equivalent to passing
- :option:`--debug <ctest --debug>` on the command line.
-
- ``outputOnFailure``
- An optional bool. If true, equivalent to passing
- :option:`--output-on-failure <ctest --output-on-failure>` on the command
- line.
-
- ``quiet``
- An optional bool. If true, equivalent to passing
- :option:`--quiet <ctest --quiet>` on the command line.
-
- ``outputLogFile``
- An optional string specifying a path to a log file. Equivalent to
- passing :option:`--output-log <ctest --output-log>` on the command line.
- This field supports macro expansion.
-
-.. _`CMakePresets outputJUnitFile`:
-
- ``outputJUnitFile``
- An optional string specifying a path to a JUnit file. Equivalent to
- passing :option:`--output-junit <ctest --output-junit>` on the command line.
- This field supports macro expansion. This is allowed in preset files
- specifying version ``6`` or above.
-
- ``labelSummary``
- An optional bool. If false, equivalent to passing
- :option:`--no-label-summary <ctest --no-label-summary>` on the command
- line.
-
- ``subprojectSummary``
- An optional bool. If false, equivalent to passing
- :option:`--no-subproject-summary <ctest --no-subproject-summary>`
- on the command line.
-
- ``maxPassedTestOutputSize``
- An optional integer specifying the maximum output for passed tests in
- bytes. Equivalent to passing
- :option:`--test-output-size-passed <ctest --test-output-size-passed>`
- on the command line.
-
- ``maxFailedTestOutputSize``
- An optional integer specifying the maximum output for failed tests in
- bytes. Equivalent to passing
- :option:`--test-output-size-failed <ctest --test-output-size-failed>`
- on the command line.
-
-.. _`CMakePresets testOutputTruncation`:
-
- ``testOutputTruncation``
- An optional string specifying the test output truncation mode. Equivalent
- to passing
- :option:`--test-output-truncation <ctest --test-output-truncation>` on
- the command line. This is allowed in preset files specifying version
- ``5`` or above.
-
- ``maxTestNameWidth``
- An optional integer specifying the maximum width of a test name to
- output. Equivalent to passing :option:`--max-width <ctest --max-width>`
- on the command line.
-
-``filter``
- An optional object specifying how to filter the tests to run. The object
- may contain the following fields.
-
- ``include``
- An optional object specifying which tests to include. The object may
- contain the following fields.
-
- ``name``
- An optional string specifying a regex for test names. Equivalent to
- passing :option:`--tests-regex <ctest --tests-regex>` on the command
- line. This field supports macro expansion. CMake regex syntax is
- described under :ref:`string(REGEX) <Regex Specification>`.
-
- ``label``
- An optional string specifying a regex for test labels. Equivalent to
- passing :option:`--label-regex <ctest --label-regex>` on the command
- line. This field supports macro expansion.
-
- ``useUnion``
- An optional bool. Equivalent to passing :option:`--union <ctest --union>`
- on the command line.
-
- ``index``
- An optional object specifying tests to include by test index. The
- object may contain the following fields. Can also be an optional
- string specifying a file with the command line syntax for
- :option:`--tests-information <ctest --tests-information>`.
- If specified as a string, this field supports macro expansion.
-
- ``start``
- An optional integer specifying a test index to start testing at.
-
- ``end``
- An optional integer specifying a test index to stop testing at.
-
- ``stride``
- An optional integer specifying the increment.
-
- ``specificTests``
- An optional array of integers specifying specific test indices to
- run.
-
- ``exclude``
- An optional object specifying which tests to exclude. The object may
- contain the following fields.
-
- ``name``
- An optional string specifying a regex for test names. Equivalent to
- passing :option:`--exclude-regex <ctest --exclude-regex>` on the
- command line. This field supports macro expansion.
-
- ``label``
- An optional string specifying a regex for test labels. Equivalent to
- passing :option:`--label-exclude <ctest --label-exclude>` on the
- command line. This field supports macro expansion.
-
- ``fixtures``
- An optional object specifying which fixtures to exclude from adding
- tests. The object may contain the following fields.
-
- ``any``
- An optional string specifying a regex for text fixtures to exclude
- from adding any tests. Equivalent to
- :option:`--fixture-exclude-any <ctest --fixture-exclude-any>` on
- the command line. This field supports macro expansion.
-
- ``setup``
- An optional string specifying a regex for text fixtures to exclude
- from adding setup tests. Equivalent to
- :option:`--fixture-exclude-setup <ctest --fixture-exclude-setup>`
- on the command line. This field supports macro expansion.
-
- ``cleanup``
- An optional string specifying a regex for text fixtures to exclude
- from adding cleanup tests. Equivalent to
- :option:`--fixture-exclude-cleanup <ctest --fixture-exclude-cleanup>`
- on the command line. This field supports macro expansion.
-
-``execution``
- An optional object specifying options for test execution. The object may
- contain the following fields.
-
- ``stopOnFailure``
- An optional bool. If true, equivalent to passing
- :option:`--stop-on-failure <ctest --stop-on-failure>` on the command
- line.
-
- ``enableFailover``
- An optional bool. If true, equivalent to passing :option:`-F <ctest -F>`
- on the command line.
-
-.. _`CMakePresets test jobs`:
-
- ``jobs``
- An optional integer. Equivalent to passing
- :option:`--parallel <ctest --parallel>` on the command line. If the value
- is ``0``, it is equivalent to unbounded parallelism.
-
- In preset files specifying version ``11`` or above, this field can also be
- a string, in which case it must be empty, and is equivalent to passing
- ``--parallel`` with ``<jobs>`` omitted.
-
- .. versionchanged:: 4.3
-
- This field does not accept negative integer values, regardless of the
- version in the preset file.
-
- ``resourceSpecFile``
- An optional string. Equivalent to passing
- :option:`--resource-spec-file <ctest --resource-spec-file>` on
- the command line. This field supports macro expansion.
-
- ``testLoad``
- An optional integer. Equivalent to passing
- :option:`--test-load <ctest --test-load>` on the command line.
-
- ``showOnly``
- An optional string. Equivalent to passing
- :option:`--show-only <ctest --show-only>` on the
- command line. The string must be one of the following values:
-
- ``human``
-
- ``json-v1``
-
- ``repeat``
- An optional object specifying how to repeat tests. Equivalent to
- passing :option:`--repeat <ctest --repeat>` on the command line.
- The object must have the following fields.
-
- ``mode``
- A required string. Must be one of the following values:
-
- ``until-fail``
-
- ``until-pass``
-
- ``after-timeout``
-
- ``count``
- A required integer.
-
- ``interactiveDebugging``
- An optional bool. If true, equivalent to passing
- :option:`--interactive-debug-mode 1 <ctest --interactive-debug-mode>`
- on the command line. If false, equivalent to passing
- :option:`--interactive-debug-mode 0 <ctest --interactive-debug-mode>`
- on the command line.
-
- ``scheduleRandom``
- An optional bool. If true, equivalent to passing
- :option:`--schedule-random <ctest --schedule-random>` on the command
- line.
-
- ``timeout``
- An optional integer. Equivalent to passing
- :option:`--timeout <ctest --timeout>` on the command line.
-
- ``noTestsAction``
- An optional string specifying the behavior if no tests are found. Must
- be one of the following values:
-
- ``default``
- Equivalent to not passing any value on the command line.
-
- ``error``
- Equivalent to passing :option:`--no-tests=error <ctest --no-tests>`
- on the command line.
-
- ``ignore``
- Equivalent to passing :option:`--no-tests=ignore <ctest --no-tests>`
- on the command line.
+.. _`Package Preset`:
Package Preset
^^^^^^^^^^^^^^
-Package presets may be used in schema version ``6`` or above. Each entry of
-the ``packagePresets`` array is a JSON object that may contain the following
-fields:
+.. presets-versionadded:: 6
-``name``
- A required string representing the machine-friendly name of the preset.
- This identifier is used in the :option:`cpack --preset` option.
- There must not be two package presets in the union of ``CMakePresets.json``
- and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a package preset may have the same name as a configure, build,
- test, or workflow preset.
+Each entry of the ``packagePresets`` array is a JSON object
+that may contain the following fields:
-``hidden``
- An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the
- :option:`--preset <cpack --preset>` argument
- and does not have to have a valid ``configurePreset``, even from
- inheritance. ``hidden`` presets are intended to be used as a base for
- other presets to inherit via the ``inherits`` field.
-
-``inherits``
- An optional array of strings representing the names of presets to inherit
- from. This field can also be a string, which is equivalent to an array
- containing one string.
-
- The preset will inherit all of the fields from the
- ``inherits`` presets by default (except ``name``, ``hidden``,
- ``inherits``, ``description``, and ``displayName``), but can override
- them as desired. If multiple ``inherits`` presets provide conflicting
- values for the same field, the earlier preset in the ``inherits`` array
- will be preferred.
-
- A preset can only inherit from another preset that is defined in the
- same file or in one of the files it includes (directly or indirectly).
- Presets in ``CMakePresets.json`` may not inherit from presets in
- ``CMakeUserPresets.json``.
-
-``condition``
- An optional `Condition`_ object.
-
-``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. If vendors use their own per-preset
- ``vendor`` field, they should implement inheritance in a sensible manner
- when appropriate.
-
-``displayName``
- An optional string with a human-friendly name of the preset.
-
-``description``
- An optional string with a human-friendly description of the preset.
-
-``environment``
- An optional map of environment variables. The key is the variable name
- (which may not be an empty string), and the value is either ``null`` or
- a string representing the value of the variable. Each variable is set
- regardless of whether or not a value was given to it by the process's
- environment.
-
- This field supports `macro expansion`_, and environment variables in this map
- may reference each other, and may be listed in any order, as long as such
- references do not cause a cycle (for example, if ``ENV_1`` is
- ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
- allows one to prepend or append values to existing environment variables by
- accessing only values from the parent environment.
-
- Environment variables are inherited through the ``inherits`` field, and
- the preset's environment will be the union of its own ``environment``
- and the ``environment`` from all its parents. If multiple presets in
- this union define the same variable, the standard rules of ``inherits``
- are applied. Setting a variable to ``null`` causes it to not be set,
- even if a value was inherited from another preset.
-
-``configurePreset``
- An optional string specifying the name of a configure preset to
- associate with this package preset. If ``configurePreset`` is not
- specified, it must be inherited from the inherits preset (unless this
- preset is hidden). The build directory is inferred from the configure
- preset, so packaging will run in the same ``binaryDir`` that the
- configuration did and build did.
-
-``inheritConfigureEnvironment``
- An optional boolean that defaults to true. If true, the environment
- variables from the associated configure preset are inherited after all
- inherited package preset environments, but before environment variables
- explicitly specified in this package preset.
-
-``generators``
- An optional array of strings representing generators for CPack to use.
-
-``configurations``
- An optional array of strings representing build configurations for CPack to
- package.
-
-``variables``
- An optional map of variables to pass to CPack, equivalent to
- :option:`-D <cpack -D>` arguments. Each key is the name of a variable, and
- the value is the string to assign to that variable.
-
-``configFile``
- An optional string representing the config file for CPack to use.
-
-``output``
- An optional object specifying output options. Valid keys are:
-
- ``debug``
- An optional boolean specifying whether or not to print debug information.
- A value of ``true`` is equivalent to passing
- :option:`--debug <cpack --debug>` on the command line.
-
- ``verbose``
- An optional boolean specifying whether or not to print verbosely. A value
- of ``true`` is equivalent to passing :option:`--verbose <cpack --verbose>`
- on the command line.
-
-``packageName``
- An optional string representing the package name.
-
- .. note::
-
- Due to problems with the implementation, this field does not affect the
- name of the final package file produced. Other aspects of the package
- may use the value though, leading to inconsistencies.
- A future CMake release may address this problem, but until then, it is
- recommended that this field not be used.
-
-``packageVersion``
- An optional string representing the package version.
-
- .. note::
-
- Due to problems with the implementation, this field does not affect the
- name of the final package file produced. Other aspects of the package
- may use the value though, leading to inconsistencies.
- A future CMake release may address this problem, but until then, it is
- recommended that this field not be used.
-
-``packageDirectory``
- An optional string representing the directory in which to place the package.
-
-``vendorName``
- An optional string representing the vendor name.
+.. include:: presets/packagePresets-properties.rst
.. _`Workflow Preset`:
Workflow Preset
^^^^^^^^^^^^^^^
-Workflow presets may be used in schema version ``6`` or above. Each entry of
-the ``workflowPresets`` array is a JSON object that may contain the following
-fields:
+.. presets-versionadded:: 6
-``name``
- A required string representing the machine-friendly name of the preset.
- This identifier is used in the
- :option:`cmake --workflow --preset <cmake--workflow --preset>` option. There
- must not be two workflow presets in the union of ``CMakePresets.json`` and
- ``CMakeUserPresets.json`` in the same directory with the same name. However,
- a workflow preset may have the same name as a configure, build, test, or
- package preset.
+Each entry of the ``workflowPresets`` array is a JSON object
+that may contain the following fields:
-``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.
-
-``description``
- An optional string with a human-friendly description of the preset.
-
-``steps``
- A required array of objects describing the steps of the workflow. The first
- step must be a configure preset, and all subsequent steps must be
- non-configure presets whose ``configurePreset`` field matches the starting
- configure preset. Each object may contain the following fields:
-
- ``type``
- A required string. The first step must be ``configure``. Subsequent steps
- must be either ``build``, ``test``, or ``package``.
-
- ``name``
- A required string representing the name of the configure, build, test, or
- package preset to run as this workflow step.
+.. include:: presets/workflowPresets-properties.rst
Condition
^^^^^^^^^
-The ``condition`` field of a preset, allowed in preset files specifying version
-``3`` or above, is used to determine whether or not the preset is enabled. For
-example, this can be used to disable a preset on platforms other than Windows.
-``condition`` may be either a boolean, ``null``, or an object. If it is a
-boolean, the boolean indicates whether the preset is enabled or disabled. If it
-is ``null``, the preset is enabled, but the ``null`` condition is not inherited
-by any presets that may inherit from the preset. Sub-conditions (for example in
-a ``not``, ``anyOf``, or ``allOf`` condition) may not be ``null``. If it is an
-object, it has the following fields:
+.. presets-versionadded:: 3
+
+The ``condition`` field of a preset is used to determine whether or not the
+preset is enabled. For example, this can be used to disable a preset on
+platforms other than Windows. ``condition`` may be either a boolean, ``null``,
+or an object. If it is a boolean, the boolean indicates whether the preset is
+enabled or disabled. If it is ``null``, the preset is enabled, but the ``null``
+condition is not inherited by any presets that may inherit from the preset.
+Sub-conditions (for example in a ``not``, ``anyOf``, or ``allOf`` condition)
+may not be ``null``. If it is an object, it has the following fields:
``type``
A required string with one of the following values:
@@ -1196,9 +163,7 @@
A required boolean which provides a constant value for the condition's
evaluation.
- ``"equals"``
-
- ``"notEquals"``
+ ``"equals"``, ``"notEquals"``
Indicates that the condition compares two strings to see if they are equal
(or not equal). The condition object will have the following additional
fields:
@@ -1209,9 +174,7 @@
``rhs``
Second string to compare. This field supports macro expansion.
- ``"inList"``
-
- ``"notInList"``
+ ``"inList"``, ``"notInList"``
Indicates that the condition searches for a string in a list of strings.
The condition object will have the following additional fields:
@@ -1222,9 +185,7 @@
A required array of strings to search. This field supports macro
expansion, and uses short-circuit evaluation.
- ``"matches"``
-
- ``"notMatches"``
+ ``"matches"``, ``"notMatches"``
Indicates that the condition searches for a regular expression in a string.
The condition object will have the following additional fields:
@@ -1235,9 +196,7 @@
A required regular expression to search for. This field supports macro
expansion.
- ``"anyOf"``
-
- ``"allOf"``
+ ``"anyOf"``, ``"allOf"``
Indicates that the condition is an aggregation of zero or more nested
conditions. The condition object will have the following additional fields:
@@ -1257,12 +216,14 @@
^^^^^^^^^^^^^^^
As mentioned above, some fields support macro expansion. Macros are
-recognized in the form ``$<macro-namespace>{<macro-name>}``. All macros are
-evaluated in the context of the preset being used, even if the macro is in a
-field that was inherited from another preset. For example, if the ``Base``
-preset sets variable ``PRESET_NAME`` to ``${presetName}``, and the
-``Derived`` preset inherits from ``Base``, ``PRESET_NAME`` will be set to
-``Derived``.
+recognized in the form ``$<macro-namespace>{<macro-name>}``.
+
+In general, macros are evaluated in the context of the preset being used, even
+if the macro is in a field that was inherited from another preset. For example,
+if the ``Base`` preset sets variable ``PRESET_NAME`` to ``${presetName}``, and
+the ``Derived`` preset inherits from ``Base``, ``PRESET_NAME`` will be set to
+``Derived``. The ``${fileDir}`` macro as of preset version ``12`` is an
+exception to this rule.
It is an error to not put a closing brace at the end of a macro name. For
example, ``${sourceDir`` is invalid. A dollar sign (``$``) followed by
@@ -1297,15 +258,47 @@
.. _`CMakePresets hostSystemName`:
``${hostSystemName}``
+ .. presets-versionadded:: 3
+
The name of the host operating system. Contains the same value as
- :variable:`CMAKE_HOST_SYSTEM_NAME`. This is allowed in preset files
- specifying version ``3`` or above.
+ :variable:`CMAKE_HOST_SYSTEM_NAME`.
.. _`CMakePresets fileDir`:
``${fileDir}``
- Path to the directory containing the preset file which contains the macro.
- This is allowed in preset files specifying version ``4`` or above.
+ .. presets-versionadded:: 4
+
+ Path to the directory containing the preset file which defines the preset
+ being used.
+
+ .. presets-versionchanged:: 12
+
+ This macro *always* expands to the directory of the current preset file
+ containing the macro, regardless of the preset being used.
+
+ For example, consider the following scenario.
+
+ * ``/path/to/CMakePresets.json`` includes
+ ``/path/to/subdir/CMakePresets.json``.
+ * ``/path/to/subdir/CMakePresets.json`` defines preset ``Base``, which
+ sets variable ``MY_DIR`` to ``${fileDir}``.
+ * ``/path/to/CMakePresets.json`` defines preset ``Derived``, and
+ ``Derived`` inherits from ``Base``.
+
+ Under preset versions ``4``-``11``, ``MY_DIR`` will be set to ``/path/to/``
+ when using the ``Base`` preset, and ``/path/to/subdir/`` when using the
+ ``Derived`` preset.
+
+ When ``/path/to/subdir/CMakePresets.json`` specifies version ``12`` or
+ above, ``MY_DIR`` will always be set to ``/path/to/subdir/``, regardless of
+ the preset being used.
+
+ .. note::
+
+ Since the ``${fileDir}`` macro in version 12 is expanded in the context
+ of the current preset file, it is the version of the current file, rather
+ than the version of the root file containing the preset being used, which
+ enables this alternative behavior.
``${dollar}``
A literal dollar sign (``$``).
@@ -1313,6 +306,8 @@
.. _`CMakePresets pathListSep`:
``${pathListSep}``
+ .. presets-versionadded:: 5
+
Native character for separating lists of paths, such as ``:`` or ``;``.
For example, by setting ``PATH`` to
@@ -1320,8 +315,6 @@
expand to the underlying operating system's character used for
concatenation in ``PATH``.
- This is allowed in preset files specifying version ``5`` or above.
-
``$env{<variable-name>}``
Environment variable with name ``<variable-name>``. The variable name may
not be an empty string. If the variable is defined in the ``environment``
@@ -1384,10 +377,10 @@
`Build <Build Preset_>`_, and `Test Presets <Test Preset_>`_.
* Changes to `Configure Presets <Configure Preset_>`_
- * The `installDir <CMakePresets installDir_>`_ field was added.
- * The `toolchainFile <CMakePresets toolchainFile_>`_ field was added.
- * The `binaryDir <CMakePresets binaryDir_>`_ field is now optional.
- * The `generator <CMakePresets generator_>`_ field is now optional.
+ * The :preset:`configurePresets.installDir` field was added.
+ * The :preset:`configurePresets.toolchainFile` field was added.
+ * The :preset:`configurePresets.binaryDir` field is now optional.
+ * The :preset:`configurePresets.generator` field is now optional.
* Changes to `Macro Expansion`_
@@ -1401,9 +394,7 @@
``CMakePresets.json`` and ``CMakeUserPresets.json``.
* Changes to `Build Presets <Build Preset_>`_
- * The
- `resolvePackageReferences <CMakePresets resolvePackageReferences_>`_
- field was added.
+ * The :preset:`buildPresets.resolvePackageReferences` field was added.
* Changes to `Macro Expansion`_
@@ -1414,8 +405,8 @@
* Changes to `Test Presets <Test Preset_>`_
- * The `testOutputTruncation <CMakePresets testOutputTruncation_>`_
- field was added to the `output <CMakePresets output_>`_ object.
+ * The :preset:`testPresets.output.testOutputTruncation` field was added
+ to the :preset:`testPresets.output` object.
* Changes to `Macro Expansion`_
@@ -1428,15 +419,15 @@
* `Workflow Presets <Workflow Preset_>`_ were added.
* Changes to `Test Presets <Test Preset_>`_
- * The `outputJUnitFile <CMakePresets outputJUnitFile_>`_ field was added
- to the `output <CMakePresets output_>`_ object.
+ * The :preset:`testPresets.output.outputJUnitFile` field was added to the
+ :preset:`testPresets.output` object.
``7``
.. versionadded:: 3.27
* Changes to `Configure Presets <Configure Preset_>`_
- * The `trace <CMakePresets trace_>`_ field was added.
+ * The :preset:`configurePresets.trace` field was added.
* Changes to `Includes`_
@@ -1445,7 +436,7 @@
``8``
.. versionadded:: 3.28
- * The `$schema <CMakePresets schema_>`_ field was added to the root object.
+ * The :preset:`$schema` field was added to the root object.
``9``
.. versionadded:: 3.30
@@ -1461,16 +452,39 @@
throughout ``CMakePresets.json`` and ``CMakeUserPresets.json``.
* Changes to `Configure Presets <Configure Preset_>`_:
- * The `graphviz <CMakePresets graphviz_>`_ field was added.
+ * The :preset:`configurePresets.graphviz` field was added.
``11``
.. versionadded:: 4.3
* Changes to `Test Presets <Test Preset_>`_
- * The `jobs <CMakePresets test jobs_>`_ field now accepts an empty string
- representing :option:`--parallel <ctest --parallel>` with ``<jobs>``
- omitted.
+ * The :preset:`testPresets.execution.jobs` field now accepts an empty
+ string representing :ctest-option:`--parallel` with ``<jobs>`` omitted.
+
+ ``12``
+ .. versionadded:: 4.4
+
+ * Changes to `Configure Presets <Configure Preset_>`_:
+
+ * The ``dev`` field is renamed to ``author`` in
+ :preset:`configurePresets.warnings` and
+ :preset:`configurePresets.errors`.
+
+ * The ``uninitialized`` and ``unusedCli`` fields were added to
+ :preset:`configurePresets.errors`.
+
+ * Changes to `Macro Expansion`_
+
+ * The `${fileDir} <CMakePresets fileDir_>`_ macro now always expands to
+ the directory of preset file containing the ``${fileDir}`` macro,
+ regardless of whether it is inherited by another preset in a different
+ directory.
+
+ * Changes to `Test Presets <Test Preset_>`_
+
+ * The :preset:`testPresets.execution.testPassthroughArguments` field was
+ added to forward arguments to test executables.
Schema
======
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 2102fc5..c8ddc04 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -307,6 +307,7 @@
/prop_tgt/INTERFACE_LINK_OPTIONS
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
/prop_tgt/INTERFACE_PRECOMPILE_HEADERS
+ /prop_tgt/INTERFACE_SOURCE_SETS
/prop_tgt/INTERFACE_SOURCES
/prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
@@ -405,9 +406,15 @@
/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG
/prop_tgt/RUNTIME_OUTPUT_NAME
/prop_tgt/RUNTIME_OUTPUT_NAME_CONFIG
+ /prop_tgt/Rust_EDITION
/prop_tgt/SKIP_BUILD_RPATH
/prop_tgt/SKIP_LINTING
/prop_tgt/SOURCE_DIR
+ /prop_tgt/SOURCE_DIRS
+ /prop_tgt/SOURCE_DIRS_NAME
+ /prop_tgt/SOURCE_SET
+ /prop_tgt/SOURCE_SET_NAME
+ /prop_tgt/SOURCE_SETS
/prop_tgt/SOURCES
/prop_tgt/SOVERSION
/prop_tgt/SPDX_LICENSE
@@ -525,6 +532,28 @@
/prop_tgt/XCODE_XCCONFIG
/prop_tgt/XCTEST
+.. _`File Set Properties`:
+
+Properties on File Sets
+=======================
+
+.. toctree::
+ :maxdepth: 1
+
+ /prop_fs/BASE_DIRS
+ /prop_fs/COMPILE_DEFINITIONS
+ /prop_fs/COMPILE_OPTIONS
+ /prop_fs/CXX_SCAN_FOR_MODULES
+ /prop_fs/INCLUDE_DIRECTORIES
+ /prop_fs/INDEPENDENT_FILES
+ /prop_fs/INTERFACE_COMPILE_DEFINITIONS
+ /prop_fs/INTERFACE_COMPILE_OPTIONS
+ /prop_fs/INTERFACE_INCLUDE_DIRECTORIES
+ /prop_fs/INTERFACE_SOURCES
+ /prop_fs/SCOPE
+ /prop_fs/SOURCES
+ /prop_fs/TYPE
+
.. _`Test Properties`:
Properties on Tests
@@ -594,6 +623,7 @@
/prop_sf/OBJECT_DEPENDS
/prop_sf/OBJECT_NAME
/prop_sf/OBJECT_OUTPUTS
+ /prop_sf/Rust_EMIT
/prop_sf/SKIP_AUTOGEN
/prop_sf/SKIP_AUTOMOC
/prop_sf/SKIP_AUTORCC
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index f9ca444..4be024d 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -577,6 +577,7 @@
/variable/CMAKE_POSITION_INDEPENDENT_CODE
/variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY
/variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG
+ /variable/CMAKE_Rust_EDITION
/variable/CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS
/variable/CMAKE_SHARED_LINKER_FLAGS
/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 62b8074..4ce3f7e 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -99,9 +99,8 @@
This chooses the kind of buildsystem to generate. See the
:manual:`cmake-generators(7)` manual for documentation of all generators.
Run :option:`cmake --help` to see a list of generators available locally.
- Optionally use the :option:`-G <cmake -G>` option below to specify a
- generator, or simply accept the default CMake chooses for the current
- platform.
+ Optionally use the :cmake-option:`-G` option below to specify a generator,
+ or simply accept the default CMake chooses for the current platform.
When using one of the :ref:`Command-Line Build Tool Generators`
CMake expects that the environment needed by the compiler toolchain
@@ -158,11 +157,11 @@
In all cases the ``<options>`` may be zero or more of the `Options`_ below.
The above styles for specifying the source and build trees may be mixed.
-Paths specified with :option:`-S <cmake -S>` or :option:`-B <cmake -B>`
-are always classified as source or build trees, respectively. Paths
-specified with plain arguments are classified based on their content
-and the types of paths given earlier. If only one type of path is given,
-the current working directory (cwd) is used for the other. For example:
+Paths specified with :cmake-option:`-S` or :cmake-option:`-B` are always
+classified as source or build trees, respectively. Paths specified with plain
+arguments are classified based on their content and the types of paths given
+earlier. If only one type of path is given, the current working directory
+(cwd) is used for the other. For example:
============================== ============ ===========
Command Line Source Dir Build Dir
@@ -225,12 +224,12 @@
List non-advanced cached variables.
List ``CACHE`` variables will run CMake and list all the variables from
- the CMake ``CACHE`` that are not marked as ``INTERNAL`` or :prop_cache:`ADVANCED`.
- This will effectively display current CMake settings, which can then be
- changed with :option:`-D <cmake -D>` option. Changing some of the variables
- may result in more variables being created. If ``A`` is specified, then it
- will display also advanced variables. If ``H`` is specified, it will also
- display help for each variable.
+ the CMake ``CACHE`` that are not marked as ``INTERNAL`` or
+ :prop_cache:`ADVANCED`. This will effectively display current CMake
+ settings, which can then be changed with :cmake-option:`-D` option.
+ Changing some of the variables may result in more variables being created.
+ If ``A`` is specified, then it will display also advanced variables.
+ If ``H`` is specified, it will also display help for each variable.
.. option:: -LR[A][H] <regex>
@@ -499,7 +498,7 @@
is an entry in the given comma-separated list of case-sensitive package
names.
- Like :option:`--debug-find <cmake --debug-find>`, but limiting scope
+ Like :cmake-option:`--debug-find`, but limiting scope
to the specified packages.
.. option:: --debug-find-var=<var>[,...]
@@ -510,7 +509,7 @@
as the result variable, where ``<var>`` is an entry in the given
comma-separated list.
- Like :option:`--debug-find <cmake --debug-find>`, but limiting scope
+ Like :cmake-option:`--debug-find`, but limiting scope
to the specified variable names.
.. option:: --trace
@@ -523,7 +522,7 @@
Put cmake in trace mode.
- Like :option:`--trace <cmake --trace>`, but with variables expanded.
+ Like :cmake-option:`--trace`, but with variables expanded.
.. option:: --trace-format=<format>
@@ -624,22 +623,23 @@
.. option:: --warn-uninitialized
- Warn about uninitialized values.
+ .. deprecated:: 4.4
- Print a warning when an uninitialized variable is used.
+ Compatibility synonym for ``-Wuninitialized``.
.. option:: --warn-unused-vars
+ .. deprecated:: 3.19
+
Does nothing. In CMake versions 3.2 and below this enabled warnings about
unused variables. In CMake versions 3.3 through 3.18 the option was broken.
In CMake 3.19 and above the option has been removed.
.. option:: --no-warn-unused-cli
- Don't warn about command line options.
+ .. deprecated:: 4.4
- Don't find variables that are declared on the command line, but not
- used.
+ Compatibility synonym for ``-Wno-unused-cli``.
.. option:: --check-system-vars
@@ -669,9 +669,8 @@
.. versionadded:: 3.18
- Used in conjunction with
- :option:`--profiling-format <cmake --profiling-format>` to output to a
- given path.
+ Used in conjunction with :cmake-option:`--profiling-format`
+ to output to a given path.
.. option:: --profiling-format=<file>
@@ -698,9 +697,9 @@
on these files, see :manual:`cmake-presets(7)`.
The presets are read before all other command line options, although the
- :option:`-S <cmake -S>` option can be used to specify the source directory
+ :cmake-option:`-S` option can be used to specify the source directory
containing the ``CMakePresets.json`` and ``CMakeUserPresets.json`` files.
- If :option:`-S <cmake -S>` is not given, the current directory is assumed to
+ If :cmake-option:`-S` is not given, the current directory is assumed to
be the top level source directory and must contain the presets files. The
options specified by the chosen preset (variables, generator, etc.) can all
be overridden by manually specifying them on the command line. For example,
@@ -717,18 +716,18 @@
Lists the available presets of the specified ``<type>``. Valid values for
``<type>`` are ``configure``, ``build``, ``test``, ``package``, or ``all``.
If ``<type>`` is omitted, ``configure`` is assumed. The current working
- directory must contain CMake preset files unless the :option:`-S <cmake -S>`
+ directory must contain CMake preset files unless the :cmake-option:`-S`
option is used to specify a different top level source directory.
.. option:: --debugger
- Enables interactive debugging of the CMake language. CMake exposes a debugging
- interface on the pipe named by :option:`--debugger-pipe <cmake --debugger-pipe>`
- that conforms to the `Debug Adapter Protocol`_ specification with the following
- modifications.
+ Enables interactive debugging of the CMake language. CMake exposes a
+ debugging interface on the pipe named by :cmake-option:`--debugger-pipe`
+ that conforms to the `Debug Adapter Protocol`_ specification with the
+ following modifications.
- The ``initialize`` response includes an additional field named ``cmakeVersion``
- which specifies the version of CMake being debugged.
+ The ``initialize`` response includes an additional field named
+ ``cmakeVersion`` which specifies the version of CMake being debugged.
.. code-block:: json
:caption: Debugger initialize response
@@ -922,6 +921,13 @@
Component-based install. Only install component ``<comp>``.
+ .. versionadded:: 4.4
+
+ Supports installing more than one component:
+
+ * ``--component <compA> <compB>``
+ * ``--component <compA> --component <compB>``
+
.. option:: --default-directory-permissions <permissions>
Default directory install permissions. Permissions in format ``<u=rwx,g=rx,o=rx>``.
@@ -1115,7 +1121,7 @@
A JSON object with version information. Keys are:
``string``
- The full version string as displayed by cmake :option:`--version <cmake --version>`.
+ The full version string as displayed by cmake :cmake-option:`--version`.
``major``
The major version number in integer form.
``minor``
@@ -1176,8 +1182,8 @@
``debugger``
.. versionadded:: 3.27
- ``true`` if the :option:`--debugger <cmake --debugger>` mode
- is supported and ``false`` otherwise.
+ ``true`` if the :cmake-option:`--debugger` mode is supported
+ and ``false`` otherwise.
.. option:: cat [--] <files>...
@@ -1200,6 +1206,10 @@
``cat`` can now print the standard input by passing the ``-`` argument.
+ .. versionadded:: 4.4
+
+ ``cat`` will print the standard input when no arguments are passed.
+
.. program:: cmake-E
.. option:: chdir <dir> <cmd> [<arg>...]
@@ -1222,11 +1232,12 @@
.. program:: cmake-E
-.. option:: copy <file>... <destination>, copy -t <destination> <file>...
+.. option:: copy <file>... <destination>,
+ copy -t <destination> <file>...
Copy files to ``<destination>`` (either file or directory).
If multiple files are specified, or if ``-t`` is specified, the
- ``<destination>`` must be directory and it must exist. If ``-t`` is not
+ ``<destination>`` must be a directory and it must exist. If ``-t`` is not
specified, the last argument is assumed to be the ``<destination>``.
Wildcards are not supported. ``copy`` does follow symlinks. That means it
does not copy symlinks, but the files or directories it point to.
@@ -1237,10 +1248,13 @@
.. versionadded:: 3.26
Support for ``-t`` argument.
-.. option:: copy_directory <dir>... <destination>
+.. option:: copy_directory <dir>... <destination>,
+ copy_directory -t <destination> <dir>...
- Copy content of ``<dir>...`` directories to ``<destination>`` directory.
- If ``<destination>`` directory does not exist it will be created.
+ Copy content of ``<dir>...`` directories to a ``<destination>`` directory.
+ If the ``<destination>`` directory does not exist it will be created.
+ If ``-t`` is not specified, the last argument is assumed to be the
+ ``<destination>``.
``copy_directory`` does follow symlinks.
.. versionadded:: 3.5
@@ -1250,52 +1264,75 @@
The command now fails when the source directory does not exist.
Previously it succeeded by creating an empty destination directory.
-.. option:: copy_directory_if_different <dir>... <destination>
+ .. versionadded:: 4.4
+ Support for the ``-t`` argument.
+
+.. option:: copy_directory_if_different <dir>... <destination>,
+ copy_directory_if_different -t <destination> <dir>...
.. versionadded:: 3.26
- Copy changed content of ``<dir>...`` directories to ``<destination>`` directory.
- If ``<destination>`` directory does not exist it will be created.
+ Copy changed content of ``<dir>...`` directories to a ``<destination>`` directory.
+ If the ``<destination>`` directory does not exist it will be created.
+ If ``-t`` is not specified, the last argument is assumed to be the
+ ``<destination>``.
``copy_directory_if_different`` does follow symlinks.
The command fails when the source directory does not exist.
-.. option:: copy_directory_if_newer <dir>... <destination>
+ .. versionadded:: 4.4
+ Support for the ``-t`` argument.
+
+.. option:: copy_directory_if_newer <dir>... <destination>,
+ copy_directory_if_newer -t <destination> <dir>...
.. versionadded:: 4.2
- Copy content of ``<dir>...`` directories to ``<destination>`` directory
+ Copy content of ``<dir>...`` directories to a ``<destination>`` directory
if source files are newer than destination files (based on file timestamps).
- If ``<destination>`` directory does not exist it will be created.
+ If the ``<destination>`` directory does not exist it will be created.
+ If ``-t`` is not specified, the last argument is assumed to be the
+ ``<destination>``.
``copy_directory_if_newer`` does follow symlinks.
The command fails when the source directory does not exist.
This is faster than ``copy_directory_if_different`` as it only compares
file timestamps instead of file contents.
-.. option:: copy_if_different <file>... <destination>
+ .. versionadded:: 4.4
+ Support for the ``-t`` argument.
+
+.. option:: copy_if_different <file>... <destination>,
+ copy_if_different -t <destination> <file>...
Copy files to ``<destination>`` (either file or directory) if
they have changed.
- If multiple files are specified, the ``<destination>`` must be
- directory and it must exist.
+ If multiple files are specified, or if ``-t`` is specified,
+ the ``<destination>`` must be a directory and it must exist.
``copy_if_different`` does follow symlinks.
.. versionadded:: 3.5
Support for multiple input files.
-.. option:: copy_if_newer <file>... <destination>
+ .. versionadded:: 4.4
+ Support for the ``-t`` argument.
+
+.. option:: copy_if_newer <file>... <destination>,
+ copy_if_newer -t <destination> <file>...
.. versionadded:: 4.2
Copy files to ``<destination>`` (either file or directory) if
source files are newer than destination files (based on file timestamps).
- If multiple files are specified, the ``<destination>`` must be
- directory and it must exist.
+ If multiple files are specified, or if ``-t`` is specified,
+ the ``<destination>`` must be a directory and it must exist.
``copy_if_newer`` does follow symlinks.
This is faster than ``copy_if_different`` as it only compares
file timestamps instead of file contents.
+ .. versionadded:: 4.4
+ Support for the ``-t`` argument.
+
.. option:: create_symlink <old> <new>
Create a symbolic link ``<new>`` naming ``<old>``.
@@ -1661,6 +1698,38 @@
not directly set by CMake itself. The default compression level
may vary between archive formats, platforms, etc.
+ .. option:: --cmake-tar-encoding=<encoding>
+
+ .. versionadded:: 4.4
+
+ Specify the pathname character encoding used in the archive.
+
+ The ``<encoding>`` may be one of:
+
+ ``UTF-8``
+ Archive pathnames are encoded as UTF-8.
+
+ This is the default since CMake 4.4.
+
+ ``OEM``
+ On Windows platforms, pathnames are encoded as using the original
+ equipment manufacturer (OEM) code page. On non-Windows platforms,
+ pathnames are encoded according to the current locale.
+
+ In CMake 4.3 and below, the ``OEM`` encoding (current locale)
+ was always used.
+
+ ``UTF-16LE``, ``UTF-16BE``
+ Archive pathnames are encoded as UTF-16 little-endian or big-endian.
+
+ ``...``
+ Any encoding name supported by ``iconv`` on the current platform.
+ On Windows, code page names may be specified.
+
+ .. note::
+ ``7zip`` archives always encode paths as ``UTF-16LE``,
+ so this option is silently ignored for that format.
+
.. option:: --cmake-tar-threads=<number>
.. versionadded:: 4.3
diff --git a/Help/manual/cpack.1.rst b/Help/manual/cpack.1.rst
index d1ca268..b6ac331 100644
--- a/Help/manual/cpack.1.rst
+++ b/Help/manual/cpack.1.rst
@@ -26,11 +26,11 @@
<cpack-generators(7)>` manual. The command ``cpack --help`` prints a
list of generators supported for the target platform. Which of them are
to be used can be selected through the :variable:`CPACK_GENERATOR` variable
-or through the command-line option :option:`-G <cpack -G>`.
+or through the command-line option :cpack-option:`-G`.
The :program:`cpack` program is steered by a configuration file written in the
:manual:`CMake language <cmake-language(7)>`. Unless chosen differently
-through the command-line option :option:`--config <cpack --config>`, the
+through the command-line option :cpack-option:`--config`, the
file ``CPackConfig.cmake`` in the current directory is used.
In the standard CMake workflow, the file ``CPackConfig.cmake`` is generated
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 2cbb41b..dba20c1 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -11,7 +11,7 @@
.. parsed-literal::
`Run Tests`_
- ctest [<options>] [--test-dir <path-to-build>]
+ ctest [<options>...] [--test-dir <path-to-build>] [-- <test-args>...]
`Build and Test Mode`_
ctest --build-and-test <path-to-source> <path-to-build>
@@ -42,6 +42,29 @@
Run Tests
=========
+:program:`ctest` runs tests defined by a ``CTestTestfile.cmake`` file,
+typically in a build tree generated by :manual:`cmake(1)`:
+
+.. code-block:: shell
+
+ ctest [<options>...] [--test-dir <path-to-build>] [-- <test-args>...]
+
+If all tests pass, the exit code is ``0``. The exit code is non-zero
+in the following cases:
+
+* An error occurs, such as failure to process invalid arguments.
+
+* .. versionadded:: 4.4
+ No arguments are given and no ``CTestTestfile.cmake`` exists.
+
+* The :ctest-option:`--no-tests=error` argument is given and no tests are
+ executed, e.g., when ``CTestTestfile.cmake`` defines no tests, or when the
+ given arguments exclude all tests.
+
+* At least one test fails.
+
+The options for running tests are:
+
.. program:: ctest
.. option:: --preset <preset>, --preset=<preset>
@@ -157,9 +180,8 @@
.. option:: --test-load <level>
- While running tests in parallel (e.g. with :option:`-j <ctest -j>`), try
- not to start tests when they may cause the CPU load to pass above a given
- threshold.
+ While running tests in parallel (e.g. with :ctest-option:`-j`), try not to
+ start tests when they may cause the CPU load to pass above a given threshold.
When :program:`ctest` is run as a `Dashboard Client`_ this sets the
``TestLoad`` option of the `CTest Test Step`_.
@@ -169,10 +191,10 @@
Make CTest quiet.
This option will suppress all the output. The output log file will
- still be generated if the :option:`--output-log <ctest --output-log>` is
- specified. Options such as :option:`--verbose <ctest --verbose>`,
- :option:`--extra-verbose <ctest --extra-verbose>`, and
- :option:`--debug <ctest --debug>` are ignored
+ still be generated if the :ctest-option:`--output-log` is specified.
+ Options such as :ctest-option:`--verbose`,
+ :ctest-option:`--extra-verbose`, and
+ :ctest-option:`--debug` are ignored
if ``--quiet`` is specified.
.. option:: -O <file>, --output-log <file>
@@ -189,16 +211,16 @@
This option tells CTest to write test results to ``<file>`` in JUnit XML
format. If ``<file>`` already exists, it will be overwritten. If using the
- :option:`-S <ctest -S>` option to run a dashboard script, use the
- ``OUTPUT_JUNIT`` keyword with the :command:`ctest_test` command instead.
+ :ctest-option:`-S` option to run a dashboard script, use the ``OUTPUT_JUNIT``
+ keyword with the :command:`ctest_test` command instead.
.. option:: -N, --show-only[=<format>]
Disable actual execution of tests.
This option tells CTest to list the tests that would be run but not
- actually run them. Useful in conjunction with the :option:`-R <ctest -R>`
- and :option:`-E <ctest -E>` options.
+ actually run them. Useful in conjunction with the :ctest-option:`-R`
+ and :ctest-option:`-E` options.
.. versionadded:: 3.14
@@ -287,13 +309,11 @@
.. option:: -FS <regex>, --fixture-exclude-setup <regex>
- Same as :option:`-FA <ctest -FA>` except only matching setup tests are
- excluded.
+ Same as :ctest-option:`-FA` except only matching setup tests are excluded.
.. option:: -FC <regex>, --fixture-exclude-cleanup <regex>
- Same as :option:`-FA <ctest -FA>` except only matching cleanup tests are
- excluded.
+ Same as :ctest-option:`-FA` except only matching cleanup tests are excluded.
.. option:: -I [Start,End,Stride,test#,test#|Test file], --tests-information
@@ -307,11 +327,11 @@
.. option:: -U, --union
- Take the Union of :option:`-I <ctest -I>` and :option:`-R <ctest -R>`.
+ Take the Union of :ctest-option:`-I` and :ctest-option:`-R`.
- When both :option:`-R <ctest -R>` and :option:`-I <ctest -I>` are specified
- by default the intersection of tests are run. By specifying ``-U`` the union
- of tests is run instead.
+ When both :ctest-option:`-R` and :ctest-option:`-I` are specified by default
+ the intersection of tests are run. By specifying ``-U`` the union of tests
+ is run instead.
.. option:: --rerun-failed
@@ -320,8 +340,8 @@
This option tells CTest to perform only the tests that failed during
its previous run. When this option is specified, CTest ignores all
other options intended to modify the list of tests to run (
- :option:`-L <ctest -L>`, :option:`-R <ctest -R>`, :option:`-E <ctest -E>`,
- :option:`-LE <ctest -LE>`, :option:`-I <ctest -I>`, etc). In the event that
+ :ctest-option:`-L`, :ctest-option:`-R`, :ctest-option:`-E`,
+ :ctest-option:`-LE`, :ctest-option:`-I`, etc). In the event that
CTest runs and no tests fail, subsequent calls to CTest with the
``--rerun-failed`` option will run the set of tests that most recently
failed (if any).
@@ -489,13 +509,21 @@
.. option:: --no-tests=<action>
- Regard no tests found either as error (when ``<action>`` is set to
- ``error``) or ignore it (when ``<action>`` is set to ``ignore``).
+ Specify behavior when no tests are executed, e.g., when
+ ``CTestTestfile.cmake`` defines no tests, or when the given arguments
+ exclude all tests. The ``<action>`` may be one of:
- If no tests were found, the default behavior of CTest is to always log an
- error message but to return an error code in script mode only. This option
- unifies the behavior of CTest by either returning an error code if no tests
- were found or by ignoring it.
+ ``error``
+ Consider running no tests to be an error.
+
+ This is the default when running :option:`ctest -S` scripts.
+
+ ``ignore``
+ Consider running no tests to be normal.
+
+ This is the default when `running tests <Run Tests_>`__ via the
+ :program:`ctest` command line, even when running as a
+ `dashboard client <Dashboard Client_>`__.
.. versionadded:: 3.26
@@ -510,6 +538,27 @@
the :ref:`cmake-instrumentation Indexing` section of CMake instrumentation for
more details.
+.. option:: -- <test-args>...
+
+ .. versionadded:: 4.4
+
+ Forward extra arguments to test executables.
+
+ All arguments after ``--`` are appended to the end of every executed
+ test's command line. This is useful for passing options to test
+ frameworks like Google Test or doctest. For example:
+
+ .. code-block:: shell
+
+ ctest -R my_test -- --gtest_filter=SomeTest.Case
+ ctest --verbose -- --success
+
+ All selected tests receive the same extra arguments.
+ Use :ctest-option:`-R` or :ctest-option:`-L` to limit
+ which tests are executed.
+
+ A bare ``--`` with no following arguments is silently ignored.
+
View Help
=========
@@ -528,17 +577,16 @@
Each individual filter is a regular expression applied to
the labels attached to a test.
-When :option:`-L <ctest -L>` is used, in order for a test to be included in a
-test run, each regular expression must match at least one
-label. Using more than one :option:`-L <ctest -L>` option means "match **all**
-of these".
+When :ctest-option:`-L` is used, in order for a test to be included in a test
+run, each regular expression must match at least one label. Using more than
+one :ctest-option:`-L` option means "match **all** of these".
-The :option:`-LE <ctest -LE>` option works just like :option:`-L <ctest -L>`,
+The :ctest-option:`-LE` option works just like :ctest-option:`-L`,
but excludes tests rather than including them. A test is excluded if each
regular expression matches at least one label.
-If a test has no labels attached to it, then :option:`-L <ctest -L>` will never
-include that test, and :option:`-LE <ctest -LE>` will never exclude that test.
+If a test has no labels attached to it, then :ctest-option:`-L` will never
+include that test, and :ctest-option:`-LE` will never exclude that test.
As an example of tests with labels, consider five tests,
with the following labels:
@@ -698,7 +746,7 @@
.. option:: --test-command
The command to run as the test step with the
- :option:`--build-and-test <ctest --build-and-test>` option.
+ :ctest-option:`--build-and-test` option.
All arguments following this keyword will be assumed to be part of the
test command line, so it must be the last option given.
@@ -745,8 +793,7 @@
This option tells CTest to act as a CDash client where the ``<model>``
can be ``Experimental``, ``Nightly``, and ``Continuous``.
- Combining ``-M`` and :option:`-T <ctest -T>` is similar to
- :option:`-D <ctest -D>`.
+ Combining ``-M`` and :ctest-option:`-T` is similar to :ctest-option:`-D`.
.. option:: -T <action>, --test-action <action>
@@ -755,8 +802,7 @@
This option tells CTest to act as a CDash client and perform some
action such as ``start``, ``build``, ``test`` etc. See
`Dashboard Client Steps`_ for the full list of actions.
- Combining :option:`-M <ctest -M>` and ``-T`` is similar to
- :option:`-D <ctest -D>`.
+ Combining :ctest-option:`-M` and ``-T`` is similar to :ctest-option:`-D`.
.. option:: -S <script>, --script <script>
@@ -772,10 +818,10 @@
Execute a dashboard for a configuration.
- This option does the same operations as :option:`-S <ctest -S>` but it
- will do them in a separate process. This is primarily useful in cases
- where the script may modify the environment and you do not want the modified
- environment to impact other :option:`-S <ctest -S>` scripts.
+ This option does the same operations as :ctest-option:`-S` but it will do
+ them in a separate process. This is primarily useful in cases where the
+ script may modify the environment and you do not want the modified
+ environment to impact other :ctest-option:`-S` scripts.
.. _`Dashboard Options`:
@@ -786,7 +832,7 @@
Define a variable for script mode.
Pass in variable values on the command line. Use in conjunction
- with :option:`-S <ctest -S>` to pass variable values to a dashboard script.
+ with :ctest-option:`-S` to pass variable values to a dashboard script.
Parsing ``-D`` arguments as variable values is only attempted if the value
following ``-D`` does not match any of the known dashboard types.
@@ -1227,9 +1273,9 @@
``DefaultCTestConfigurationType``
When the build system to be launched allows build-time selection
of the configuration (e.g. ``Debug``, ``Release``), this specifies
- the default configuration to be built when no :option:`-C <ctest -C>`
- option is given to the :program:`ctest` command. The value will be substituted
- into the value of ``MakeCommand`` to replace the literal string
+ the default configuration to be built when no :ctest-option:`-C`
+ option is given to the :program:`ctest` command. The value will be
+ substituted into the value of ``MakeCommand`` to replace the literal string
``${CTEST_CONFIGURATION_TYPE}`` if it appears.
* `CTest Script`_ variable: :variable:`CTEST_CONFIGURATION_TYPE`
@@ -1301,7 +1347,7 @@
See `Label and Subproject Summary`_.
``TestLoad``
- While running tests in parallel (e.g. with :option:`-j <ctest -j>`),
+ While running tests in parallel (e.g. with :ctest-option:`-j`),
try not to start tests when they may cause the CPU load to pass above
a given threshold.
@@ -1311,7 +1357,7 @@
``TimeOut``
The default timeout for each test if not specified by the
:prop_test:`TIMEOUT` test property or the
- :option:`--timeout <ctest --timeout>` flag.
+ :ctest-option:`--timeout` flag.
* `CTest Script`_ variable: :variable:`CTEST_TEST_TIMEOUT`
* :module:`CTest` module variable: ``DART_TESTING_TIMEOUT``
@@ -1677,7 +1723,7 @@
Test name. This cannot be empty.
``config``
Optional field specifying the configuration for which the test will run.
- This will always match the :option:`-C <ctest -C>` option specified on the
+ This will always match the :ctest-option:`-C` option specified on the
``ctest`` command line. If no such option was given, this field will not
be present.
``command``
@@ -1795,11 +1841,10 @@
If a dashboard script is used and ``RESOURCE_SPEC_FILE`` is not specified, the
value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script is used
-instead. If :option:`--resource-spec-file <ctest --resource-spec-file>`,
-``RESOURCE_SPEC_FILE``, and :variable:`CTEST_RESOURCE_SPEC_FILE` in the
-dashboard script are not specified, the value of
-:variable:`CTEST_RESOURCE_SPEC_FILE` in the CMake build is used instead.
-If none of these are specified, no resource spec file is used.
+instead. If :ctest-option:`--resource-spec-file`, ``RESOURCE_SPEC_FILE``, and
+:variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script are not specified,
+the value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the CMake build is used
+instead. If none of these are specified, no resource spec file is used.
The resource specification file must be a JSON object. All examples in this
document assume the following resource specification file:
@@ -1996,9 +2041,9 @@
On POSIX systems, when running under the context of a `Job Server`_,
CTest shares its job slots. This is independent of the :prop_test:`PROCESSORS`
-test property, which still counts against CTest's :option:`-j <ctest -j>`
-parallel level. CTest acquires exactly one token from the job server before
-running each test, and returns it when the test finishes.
+test property, which still counts against CTest's :ctest-option:`-j` parallel
+level. CTest acquires exactly one token from the job server before running
+each test, and returns it when the test finishes.
For example, consider the ``Makefile``:
diff --git a/Help/manual/include/OPTIONS_BUILD.rst b/Help/manual/include/OPTIONS_BUILD.rst
index 4d8f88e..851cb9d 100644
--- a/Help/manual/include/OPTIONS_BUILD.rst
+++ b/Help/manual/include/OPTIONS_BUILD.rst
@@ -138,59 +138,34 @@
transition and not for publication of a final product. CMake will always emit
a warning when the project file is anything other than ``CMakeLists.txt``.
-.. option:: -Wno-dev
+.. option:: -W<category>
- Suppress developer warnings.
+ Promote the specified diagnostic category (and any children) to at least
+ ``WARN`` severity. Note that this has no effect on diagnostics already set to
+ a higher severity.
- Suppress warnings that are meant for the author of the
- ``CMakeLists.txt`` files. By default this will also turn off
- deprecation warnings.
+ See the :manual:`cmake-diagnostics(7)` manual for a list of accepted values
+ for ``<category>``.
-.. option:: -Wdev
+.. option:: -Wno-<category>
- Enable developer warnings.
+ Disable (ignore) all diagnostics of the specified category, including any
+ child categories.
- Enable warnings that are meant for the author of the ``CMakeLists.txt``
- files. By default this will also turn on deprecation warnings.
+.. option:: -Werror=<category>
-.. option:: -Wdeprecated
+ Promote the specified diagnostic category (and any children) to at least
+ ``SEND_ERROR`` severity. Note that this has no effect on diagnostics already
+ set to a higher severity.
- Enable deprecated functionality warnings.
+.. option:: -Wno-error=<category>
- Enable warnings for usage of deprecated functionality, that are meant
- for the author of the ``CMakeLists.txt`` files.
+ Demote the specified diagnostic category (and any children) to at most
+ ``WARN`` severity. Note that this has no effect on diagnostics already
+ set to a lower severity.
-.. option:: -Wno-deprecated
+.. option:: -Wdev, -Wno-dev
- Suppress deprecated functionality warnings.
+ .. deprecated:: 4.4
- Suppress warnings for usage of deprecated functionality, that are meant
- for the author of the ``CMakeLists.txt`` files.
-
-.. option:: -Werror=<what>
-
- Treat CMake warnings as errors. ``<what>`` must be one of the following:
-
- ``dev``
- Make developer warnings errors.
-
- Make warnings that are meant for the author of the ``CMakeLists.txt`` files
- errors. By default this will also turn on deprecated warnings as errors.
-
- ``deprecated``
- Make deprecated macro and function warnings errors.
-
- Make warnings for usage of deprecated macros and functions, that are meant
- for the author of the ``CMakeLists.txt`` files, errors.
-
-.. option:: -Wno-error=<what>
-
- Do not treat CMake warnings as errors. ``<what>`` must be one of the following:
-
- ``dev``
- Make warnings that are meant for the author of the ``CMakeLists.txt`` files not
- errors. By default this will also turn off deprecated warnings as errors.
-
- ``deprecated``
- Make warnings for usage of deprecated macros and functions, that are meant
- for the author of the ``CMakeLists.txt`` files, not errors.
+ Compatibility synonyms for ``-Wauthor`` / ``-Wno-author``.
diff --git a/Help/manual/instrumentation/index-v1-schema.json b/Help/manual/instrumentation/index-v1-schema.json
new file mode 100644
index 0000000..6b59bb6
--- /dev/null
+++ b/Help/manual/instrumentation/index-v1-schema.json
@@ -0,0 +1,169 @@
+{
+ "$schema": "http://json-schema.org/draft/2020-12/schema#",
+ "type": "object",
+ "required": [
+ "version",
+ "buildDir",
+ "dataDir",
+ "hook",
+ "snippets"
+ ],
+ "definitions": {
+ "nonEmptyStringOrNull": {
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "positiveIntegerOrNull": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1
+ },
+ {
+ "type": "null"
+ }
+ ]
+ }
+ },
+ "properties": {
+ "version": {
+ "type": "integer",
+ "description": "The data version of the index file.",
+ "enum": [
+ 1
+ ]
+ },
+ "buildDir": {
+ "type": "string",
+ "description": "The build directory of the CMake project.",
+ "minLength": 1
+ },
+ "dataDir": {
+ "type": "string",
+ "description": "The full path to the <build>/.cmake/instrumentation/v1/data/ directory.",
+ "minLength": 1
+ },
+ "hook": {
+ "type": "string",
+ "description": "The name of the hook responsible for generating the index file. In addition to the hooks that can be specified by one of the v1 Query Files, this value may be set to manual if indexing is performed by invoking ctest --collect-instrumentation.",
+ "enum": [
+ "postGenerate",
+ "preBuild",
+ "postBuild",
+ "preCMakeBuild",
+ "postCMakeBuild",
+ "postCMakeInstall",
+ "postCMakeWorkflow",
+ "postCTest",
+ "manual"
+ ]
+ },
+ "snippets": {
+ "type": "array",
+ "description": "Contains a list of v1 Snippet Files. This includes all snippet files generated since the previous index file was created. The file paths are relative to dataDir.",
+ "items": {
+ "type": "string",
+ "minLength": 1
+ },
+ "uniqueItems": true
+ },
+ "trace": {
+ "type": "string",
+ "description": "Contains the path to the Google Trace File. This includes data from all corresponding snippets in the index file. The file path is relative to dataDir. Only included when enabled by the v1 Query Files.",
+ "minLength": 1
+ },
+ "staticSystemInformation": {
+ "type": "object",
+ "description": "Specifies the static information collected about the host machine CMake is being run from. Only included when enabled by the v1 Query Files.",
+ "properties": {
+ "OSName": {
+ "description": "The host operating system name.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "OSPlatform": {
+ "description": "The name of the CPU CMake is running on.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "OSRelease": {
+ "description": "The OS sub-type (e.g., 'Professional' on Windows).",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "OSVersion": {
+ "description": "The OS build ID.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "familyId": {
+ "description": "The processor family name.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "hostname": {
+ "description": "Hostname.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "is64Bits": {
+ "type": "boolean",
+ "description": "True if processor is 64 bit."
+ },
+ "modelId": {
+ "description": "The processor model ID",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "numberOfLogicalCPU": {
+ "description": "Number of logical cores.",
+ "$ref": "#/definitions/positiveIntegerOrNull"
+ },
+ "numberOfPhysicalCPU": {
+ "description": "Number of physical cores.",
+ "$ref": "#/definitions/positiveIntegerOrNull"
+ },
+ "processorAPICID": {
+ "description": "The processor APIC ID.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "processorCacheSize": {
+ "description": "The processor L1 cache size.",
+ "$ref": "#/definitions/positiveIntegerOrNull"
+ },
+ "processorClockFrequency": {
+ "description": "The processor clock frequency.",
+ "anyOf": [
+ {
+ "type": "number",
+ "minimum": 1
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "processorName": {
+ "description": "Human readable processor name.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "totalPhysicalMemory": {
+ "description": "Total physical memory in MiB",
+ "$ref": "#/definitions/positiveIntegerOrNull"
+ },
+ "totalVirtualMemory": {
+ "description": "Total virtual memory in MiB",
+ "$ref": "#/definitions/positiveIntegerOrNull"
+ },
+ "vendorID": {
+ "description": "The processor vendor ID.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ },
+ "vendorString": {
+ "description": "The processor vendor string.",
+ "$ref": "#/definitions/nonEmptyStringOrNull"
+ }
+ }
+ }
+ }
+}
diff --git a/Help/manual/presets/architecture-properties.rst b/Help/manual/presets/architecture-properties.rst
new file mode 100644
index 0000000..31182b5
--- /dev/null
+++ b/Help/manual/presets/architecture-properties.rst
@@ -0,0 +1,27 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.architecture.value`:
+
+``value``
+ An optional string representing the value.
+
+.. _`CMakePresets.configurePresets.architecture.strategy`:
+
+``strategy``
+ An optional string telling CMake how to handle the field.
+ Valid values are:
+
+ ``"set"``
+ Set the respective value. This will result in an error for generators
+ that do not support the respective field.
+
+ ``"external"``
+ Do not set the value, even if the generator supports it. This is
+ useful if, for example, a preset uses the Ninja generator, and an IDE
+ knows how to set up the Visual C++ environment from the architecture
+ and toolset fields. In that case, CMake will ignore the field, but
+ the IDE can use them to set up the environment before invoking CMake.
+
+ If no ``strategy`` field is given, or if the field uses the string form
+ rather than the object form, the behavior is the same as ``"set"``.
diff --git a/Help/manual/presets/buildPresets-properties.rst b/Help/manual/presets/buildPresets-properties.rst
new file mode 100644
index 0000000..842ee40
--- /dev/null
+++ b/Help/manual/presets/buildPresets-properties.rst
@@ -0,0 +1,213 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.buildPresets.name`:
+
+``name``
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the
+ :option:`cmake --build --preset <cmake--build --preset>` option.
+ There must not be two build presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a build preset may have the
+ same name as a configure, test, package, or workflow preset.
+
+.. _`CMakePresets.buildPresets.hidden`:
+
+``hidden``
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :cmake-build-option:`--preset` argument and does not have to have a
+ valid ``configurePreset``, even from inheritance. ``hidden``
+ presets are intended to be used as a base for other presets to
+ inherit via the ``inherits`` field.
+
+.. _`CMakePresets.buildPresets.inherits`:
+
+``inherits``
+ An optional array of strings representing the names of presets from which
+ to inherit. This field can also be a string, which is equivalent to an
+ array containing one string.
+
+ The preset will inherit all of the fields from the ``inherits`` presets
+ by default (except ``name``, ``hidden``, ``inherits``, ``description``,
+ and ``displayName``), but can override them as desired. If multiple
+ ``inherits`` presets provide conflicting values for the same field, the
+ earlier preset in the ``inherits`` array will be preferred.
+
+ A preset can only inherit from another preset that is defined in the same
+ file or in one of the files it includes (directly or indirectly). Presets
+ in ``CMakePresets.json`` may not inherit from presets in
+ ``CMakeUserPresets.json``.
+
+.. _`CMakePresets.buildPresets.condition`:
+
+``condition``
+ .. presets-versionadded:: 3
+
+ An optional `Condition`_ object.
+
+.. _`CMakePresets.buildPresets.vendor`:
+
+``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. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+.. _`CMakePresets.buildPresets.displayName`:
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
+
+.. _`CMakePresets.buildPresets.description`:
+
+``description``
+ An optional string with a human-friendly description of the preset.
+
+.. _`CMakePresets.buildPresets.environment`:
+
+``environment``
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or a
+ string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment.
+
+ This field supports `macro expansion`_, and environment variables in this
+ map may reference each other, and may be listed in any order, as long as
+ such references do not cause a cycle (for example, if ``ENV_1`` is
+ ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
+ allows one to prepend or append values to existing environment variables
+ by accessing only values from the parent environment.
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+ .. note::
+
+ For a CMake project using :module:`ExternalProject` with a
+ configuration preset having environment variables needed in the
+ ExternalProject, use a build preset that inherits that
+ configuration preset or the ExternalProject will not have the
+ environment variables set in the configuration preset. Example:
+ suppose the host defaults to one compiler (say Clang) and the user
+ wishes to use another compiler (say GCC). Set configuration preset
+ environment variables :envvar:`CC` and :envvar:`CXX` and use a
+ build preset that inherits that configuration preset. Otherwise the
+ ExternalProject may use a different (system default) compiler than
+ the top-level CMake project.
+
+
+.. _`CMakePresets.buildPresets.configurePreset`:
+
+``configurePreset``
+ An optional string specifying the name of a configure preset to
+ associate with this build preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset, so the build will take place in the same
+ ``binaryDir`` that the configuration did.
+
+.. _`CMakePresets.buildPresets.inheritConfigureEnvironment`:
+
+``inheritConfigureEnvironment``
+ An optional boolean that defaults to ``true``. If ``true``, the
+ environment variables from the associated configure preset are
+ inherited after all inherited build preset environments, but before
+ environment variables explicitly specified in this build preset.
+
+.. _`CMakePresets.buildPresets.jobs`:
+
+``jobs``
+ An optional integer. Equivalent to passing
+ :cmake-build-option:`--parallel` or ``-j`` on the command line.
+ If the value is ``0``, it is equivalent to passing ``--parallel``
+ with ``<jobs>`` omitted; alternatively, one can define the
+ environment variable :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` as an
+ empty string using the ``environment`` field.
+
+ .. versionchanged:: 4.3
+
+ This field does not accept negative integer values, regardless of
+ the version in the preset file.
+
+.. _`CMakePresets.buildPresets.targets`:
+
+``targets``
+ An optional string or array of strings. Equivalent to passing
+ :cmake-build-option:`--target` or ``-t`` on the command line.
+ Vendors may ignore the targets property or hide build presets that
+ explicitly specify targets. This field supports `macro expansion`_.
+
+.. _`CMakePresets.buildPresets.configuration`:
+
+``configuration``
+ An optional string. Equivalent to passing
+ :cmake-build-option:`--config` on the command line.
+
+.. _`CMakePresets.buildPresets.cleanFirst`:
+
+``cleanFirst``
+ An optional bool. If ``true``, equivalent to passing
+ :cmake-build-option:`--clean-first` on the command line.
+
+.. _`CMakePresets.buildPresets.resolvePackageReferences`:
+
+``resolvePackageReferences``
+ .. presets-versionadded:: 4
+
+ An optional string that specifies the package resolve mode.
+
+ Package references are used to define dependencies to packages from
+ external package managers. Currently only NuGet in combination with
+ the :ref:`Visual Studio generators` is supported. If there are no
+ targets that define package references, this option does nothing.
+ Valid values are:
+
+ ``on``
+ Causes package references to be resolved before attempting a
+ build.
+
+ ``off``
+ Package references will not be resolved. Note that this may cause
+ errors in some build environments, such as .NET SDK style
+ projects.
+
+ ``only``
+ Only resolve package references, but do not perform a build.
+
+ .. note::
+
+ The command line parameter
+ :cmake-build-option:`--resolve-package-references`
+ will take priority over this setting. If the command line
+ parameter is not provided and this setting is not specified, an
+ environment-specific cache variable will be evaluated to decide,
+ if package restoration should be performed.
+
+ When using the :ref:`Visual Studio generators`,
+ package references are defined using the
+ :prop_tgt:`VS_PACKAGE_REFERENCES` property. Package references
+ are restored using NuGet. It can be disabled by setting the
+ :variable:`CMAKE_VS_NUGET_PACKAGE_RESTORE` variable to ``OFF``.
+ This can also be done from within a configure preset.
+
+.. _`CMakePresets.buildPresets.verbose`:
+
+``verbose``
+ An optional boolean. If ``true``, equivalent to passing
+ :cmake-build-option:`--verbose` on the command line.
+
+.. _`CMakePresets.buildPresets.nativeToolOptions`:
+
+``nativeToolOptions``
+ An optional array of strings. Equivalent to passing options after
+ :cmake-build-option:`--` on the command line. The array values
+ support `macro expansion`_.
diff --git a/Help/manual/presets/cacheVariables-properties.rst b/Help/manual/presets/cacheVariables-properties.rst
new file mode 100644
index 0000000..76e1a66
--- /dev/null
+++ b/Help/manual/presets/cacheVariables-properties.rst
@@ -0,0 +1,7 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.cacheVariables.type`:
+
+``type``
+ An optional string representing the type of the variable. It should be BOOL, FILEPATH, PATH, STRING, or INTERNAL.
diff --git a/Help/manual/presets/cmakeMinimumRequired-properties.rst b/Help/manual/presets/cmakeMinimumRequired-properties.rst
new file mode 100644
index 0000000..e3ede9b
--- /dev/null
+++ b/Help/manual/presets/cmakeMinimumRequired-properties.rst
@@ -0,0 +1,17 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.cmakeMinimumRequired.major`:
+
+``major``
+ An optional integer representing the major version.
+
+.. _`CMakePresets.cmakeMinimumRequired.minor`:
+
+``minor``
+ An optional integer representing the minor version.
+
+.. _`CMakePresets.cmakeMinimumRequired.patch`:
+
+``patch``
+ An optional integer representing the patch version.
diff --git a/Help/manual/presets/configurePresets-properties.rst b/Help/manual/presets/configurePresets-properties.rst
new file mode 100644
index 0000000..c15874b
--- /dev/null
+++ b/Help/manual/presets/configurePresets-properties.rst
@@ -0,0 +1,251 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.name`:
+
+``name``
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the :option:`cmake --preset`
+ option. There must not be two configure presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a configure preset may have
+ the same name as a build, test, package, or workflow preset.
+
+.. _`CMakePresets.configurePresets.hidden`:
+
+``hidden``
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :cmake-option:`--preset` argument, will not show up in the
+ :manual:`CMake GUI <cmake-gui(1)>`, and does not have to have a
+ valid ``generator`` or ``binaryDir``, even from inheritance.
+ ``hidden`` presets are intended to be used as a base for other
+ presets to inherit via the ``inherits`` field.
+
+.. _`CMakePresets.configurePresets.inherits`:
+
+``inherits``
+ An optional array of strings representing the names of presets from which
+ to inherit. This field can also be a string, which is equivalent to an
+ array containing one string.
+
+ The preset will inherit all of the fields from the ``inherits`` presets
+ by default (except ``name``, ``hidden``, ``inherits``, ``description``,
+ and ``displayName``), but can override them as desired. If multiple
+ ``inherits`` presets provide conflicting values for the same field, the
+ earlier preset in the ``inherits`` array will be preferred.
+
+ A preset can only inherit from another preset that is defined in the same
+ file or in one of the files it includes (directly or indirectly). Presets
+ in ``CMakePresets.json`` may not inherit from presets in
+ ``CMakeUserPresets.json``.
+
+.. _`CMakePresets.configurePresets.condition`:
+
+``condition``
+ .. presets-versionadded:: 3
+
+ An optional `Condition`_ object.
+
+.. _`CMakePresets.configurePresets.vendor`:
+
+``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. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+.. _`CMakePresets.configurePresets.displayName`:
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
+
+.. _`CMakePresets.configurePresets.description`:
+
+``description``
+ An optional string with a human-friendly description of the preset.
+
+.. _`CMakePresets.configurePresets.generator`:
+
+``generator``
+ An optional string representing the
+ :manual:`generator <cmake-generators(7)>` to use for the preset.
+
+ .. presets-versionchanged:: 3
+
+ If omitted, CMake will fall back to regular generator discovery
+ procedure. In previous versions, if not specified, this field
+ must be inherited from the ``inherits`` preset (unless this
+ preset is ``hidden``).
+
+ Note that for :ref:`Visual Studio generators`, unlike in the
+ command line :cmake-option:`-G` argument, you cannot include the
+ platform name in the generator name. Use the ``architecture``
+ field instead.
+
+.. _`CMakePresets.configurePresets.architecture`:
+
+``architecture``
+ Optional field representing the platform for
+ :manual:`generators <cmake-generators(7)>` that support it.
+
+ See :option:`cmake -A` for possible values.
+
+ ``architecture`` may be either a string or an object with the
+ following fields:
+
+ .. include:: presets/architecture-properties.rst
+
+.. _`CMakePresets.configurePresets.toolset`:
+
+``toolset``
+ Optional field representing the toolset for
+ :manual:`generators <cmake-generators(7)>` that support it.
+
+ See :option:`cmake -T` for possible values.
+
+ ``toolset`` may be either a string or an object with the following
+ fields:
+
+ .. include:: presets/toolset-properties.rst
+
+.. _`CMakePresets.configurePresets.toolchainFile`:
+
+``toolchainFile``
+ .. presets-versionadded:: 3
+
+ An optional string representing the path to the toolchain file.
+ This field supports `macro expansion`_. If a relative path is
+ specified, it is calculated relative to the build directory, and if
+ not found, relative to the source directory. This field takes
+ precedence over any :variable:`CMAKE_TOOLCHAIN_FILE` value.
+
+.. _`CMakePresets.configurePresets.graphviz`:
+
+``graphviz``
+ .. presets-versionadded:: 10
+
+ An optional string representing the path to the graphviz input
+ file, that will contain all the library and executable dependencies
+ in the project. See the documentation for
+ :option:`cmake --graphviz` for more details.
+
+ This field supports `macro expansion`_. If a relative path is
+ specified, it is calculated relative to the current working
+ directory.
+
+.. _`CMakePresets.configurePresets.binaryDir`:
+
+``binaryDir``
+ An optional string representing the path to the output binary
+ directory. This field supports `macro expansion`_. If a relative
+ path is specified, it is calculated relative to the source
+ directory.
+
+ .. presets-versionchanged:: 3
+
+ If omitted, CMake will calculate the path using regular methods.
+ In previous versions, if not specified, this field must be
+ inherited from the ``inherits`` preset (unless this preset is
+ ``hidden``).
+
+.. _`CMakePresets.configurePresets.installDir`:
+
+``installDir``
+ .. presets-versionadded:: 3
+
+ An optional string representing the path to the installation
+ directory, which will be used as the
+ :variable:`CMAKE_INSTALL_PREFIX` variable. This field supports
+ `macro expansion`_. If a relative path is specified, it is
+ calculated relative to the source directory.
+
+.. _`CMakePresets.configurePresets.cmakeExecutable`:
+
+``cmakeExecutable``
+ An optional string representing the path to the CMake executable to use for this preset. This is reserved for use by IDEs, and is not used by CMake itself. IDEs that use this field should expand any macros in it.
+
+.. _`CMakePresets.configurePresets.cacheVariables`:
+
+``cacheVariables``
+ An optional map of cache variables. The key is the variable name
+ (which may not be an empty string), and the value is either
+ ``null``, a boolean (which is equivalent to a value of ``"TRUE"``
+ or ``"FALSE"`` and a type of ``BOOL``), a string representing the
+ value of the variable (which supports `macro expansion`_), or an
+ object with the following fields:
+
+ ``type``
+ An optional string representing the type of the variable.
+
+ ``value``
+ A required string or boolean representing the value of the
+ variable. A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``.
+ This field supports `macro expansion`_.
+
+ Cache variables are inherited through the ``inherits`` field, and
+ the preset's variables will be the union of its own
+ ``cacheVariables`` and the ``cacheVariables`` from all its parents.
+ If multiple presets in this union define the same variable, the
+ standard rules of ``inherits`` are applied. Setting a variable to
+ ``null`` causes it to not be set, even if a value was inherited
+ from another preset.
+
+.. _`CMakePresets.configurePresets.environment`:
+
+``environment``
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or a
+ string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment.
+
+ This field supports `macro expansion`_, and environment variables in this
+ map may reference each other, and may be listed in any order, as long as
+ such references do not cause a cycle (for example, if ``ENV_1`` is
+ ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
+ allows one to prepend or append values to existing environment variables
+ by accessing only values from the parent environment.
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+.. _`CMakePresets.configurePresets.warnings`:
+
+``warnings``
+ An optional object specifying the warnings to enable.
+ The object may contain the following fields:
+
+ .. include:: presets/warnings-properties.rst
+
+.. _`CMakePresets.configurePresets.errors`:
+
+``errors``
+ An optional object specifying the errors to enable.
+ The object may contain the following fields:
+
+ .. include:: presets/errors-properties.rst
+
+.. _`CMakePresets.configurePresets.debug`:
+
+``debug``
+ An optional object specifying debug options.
+ The object may contain the following fields:
+
+ .. include:: presets/debug-properties.rst
+
+.. _`CMakePresets.configurePresets.trace`:
+
+``trace``
+ .. presets-versionadded:: 7
+
+ An optional object specifying trace options.
+ The object may contain the following fields:
+
+ .. include:: presets/trace-properties.rst
diff --git a/Help/manual/presets/debug-properties.rst b/Help/manual/presets/debug-properties.rst
new file mode 100644
index 0000000..6c8cbde
--- /dev/null
+++ b/Help/manual/presets/debug-properties.rst
@@ -0,0 +1,20 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.debug.output`:
+
+``output``
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--debug-output` on the command line.
+
+.. _`CMakePresets.configurePresets.debug.tryCompile`:
+
+``tryCompile``
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--debug-trycompile` on the command line.
+
+.. _`CMakePresets.configurePresets.debug.find`:
+
+``find``
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--debug-find` on the command line.
diff --git a/Help/manual/presets/errors-properties.rst b/Help/manual/presets/errors-properties.rst
new file mode 100644
index 0000000..af41185
--- /dev/null
+++ b/Help/manual/presets/errors-properties.rst
@@ -0,0 +1,60 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.errors.author`:
+
+``author``
+ .. presets-versionadded:: 12
+
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=author` or
+ :cmake-option:`-Wno-error=author`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.author`` is set to ``false``.
+
+.. _`CMakePresets.configurePresets.errors.deprecated`:
+
+``deprecated``
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=deprecated` or
+ :cmake-option:`-Wno-error=deprecated`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.deprecated`` is set to ``false``.
+
+.. _`CMakePresets.configurePresets.errors.dev`:
+
+``dev``
+ .. presets-versionremoved:: 12
+
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=dev` or
+ :cmake-option:`-Wno-error=dev`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.dev`` is set to ``false``.
+
+.. _`CMakePresets.configurePresets.errors.uninitialized`:
+
+``uninitialized``
+ .. presets-versionadded:: 12
+
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=uninitialized` or
+ :cmake-option:`-Wno-error=uninitialized`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.uninitialized`` is set to ``false``.
+
+.. _`CMakePresets.configurePresets.errors.unusedCli`:
+
+``unusedCli``
+ .. presets-versionadded:: 12
+
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=unused-cli` or
+ :cmake-option:`-Wno-error=unused-cli`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.unusedCli`` is set to ``false``.
diff --git a/Help/manual/presets/exclude-properties.rst b/Help/manual/presets/exclude-properties.rst
new file mode 100644
index 0000000..24775b5
--- /dev/null
+++ b/Help/manual/presets/exclude-properties.rst
@@ -0,0 +1,25 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.filter.exclude.name`:
+
+``name``
+ An optional string specifying a regex for test names.
+ Equivalent to passing :ctest-option:`--exclude-regex` on
+ the command line. This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.filter.exclude.label`:
+
+``label``
+ An optional string specifying a regex for test labels.
+ Equivalent to passing :ctest-option:`--label-exclude` on
+ the command line. This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.filter.exclude.fixtures`:
+
+``fixtures``
+ An optional object specifying which fixtures to exclude
+ from adding tests. The object may contain the following
+ fields:
+
+ .. include:: presets/fixtures-properties.rst
diff --git a/Help/manual/presets/execution-properties.rst b/Help/manual/presets/execution-properties.rst
new file mode 100644
index 0000000..ebe80fc
--- /dev/null
+++ b/Help/manual/presets/execution-properties.rst
@@ -0,0 +1,115 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.execution.stopOnFailure`:
+
+``stopOnFailure``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--stop-on-failure` on the command line.
+
+.. _`CMakePresets.testPresets.execution.enableFailover`:
+
+``enableFailover``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`-F` on the command line.
+
+.. _`CMakePresets.testPresets.execution.jobs`:
+
+``jobs``
+ An optional integer. Equivalent to passing
+ :ctest-option:`--parallel` on the command line. If the value is
+ ``0``, it is equivalent to unbounded parallelism.
+
+ .. presets-versionchanged:: 11
+
+ This field can also be a string, in which case it must be
+ empty, and is equivalent to passing ``--parallel`` with
+ ``<jobs>`` omitted.
+
+ .. versionchanged:: 4.3
+
+ This field does not accept negative integer values,
+ regardless of the version in the preset file.
+
+.. _`CMakePresets.testPresets.execution.resourceSpecFile`:
+
+``resourceSpecFile``
+ An optional string. Equivalent to passing
+ :ctest-option:`--resource-spec-file` on the command line. This
+ field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.execution.testLoad`:
+
+``testLoad``
+ An optional integer. Equivalent to passing
+ :ctest-option:`--test-load` on the command line.
+
+.. _`CMakePresets.testPresets.execution.showOnly`:
+
+``showOnly``
+ An optional string. Equivalent to passing
+ :ctest-option:`--show-only` on the command line. The string
+ must be one of the following values:
+
+ * ``human``
+
+ * ``json-v1``
+
+.. _`CMakePresets.testPresets.execution.repeat`:
+
+``repeat``
+ An optional object specifying how to repeat tests. Equivalent
+ to passing :ctest-option:`--repeat` on the command line.
+ The object must have the following fields:
+
+ .. include:: presets/repeat-properties.rst
+
+.. _`CMakePresets.testPresets.execution.interactiveDebugging`:
+
+``interactiveDebugging``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--interactive-debug-mode 1` on the command line.
+ If ``false``, equivalent to passing
+ :ctest-option:`--interactive-debug-mode 0` on the command line.
+
+.. _`CMakePresets.testPresets.execution.scheduleRandom`:
+
+``scheduleRandom``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--schedule-random` on the command line.
+
+.. _`CMakePresets.testPresets.execution.timeout`:
+
+``timeout``
+ An optional integer. Equivalent to passing
+ :ctest-option:`--timeout` on the command line.
+
+.. _`CMakePresets.testPresets.execution.noTestsAction`:
+
+``noTestsAction``
+ An optional string specifying the behavior if no tests are
+ found. Must be one of the following values:
+
+ ``default``
+ Equivalent to not passing any value on the command line.
+
+ ``error``
+ Equivalent to passing :ctest-option:`--no-tests=error`
+ on the command line.
+
+ ``ignore``
+ Equivalent to passing :ctest-option:`--no-tests=ignore`
+ on the command line.
+
+.. _`CMakePresets.testPresets.execution.testPassthroughArguments`:
+
+``testPassthroughArguments``
+ .. presets-versionadded:: 12
+
+ An optional array of strings. Each element is forwarded as an
+ argument to every test executable, equivalent to passing
+ arguments after :option:`ctest --` on the command line.
+
+ When both preset and command-line passthrough arguments are
+ specified, preset arguments appear first, followed by
+ command-line arguments.
diff --git a/Help/manual/presets/filter-properties.rst b/Help/manual/presets/filter-properties.rst
new file mode 100644
index 0000000..083e268
--- /dev/null
+++ b/Help/manual/presets/filter-properties.rst
@@ -0,0 +1,18 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.filter.include`:
+
+``include``
+ An optional object specifying which tests to include.
+ The object may contain the following fields:
+
+ .. include:: presets/include-properties.rst
+
+.. _`CMakePresets.testPresets.filter.exclude`:
+
+``exclude``
+ An optional object specifying which tests to exclude.
+ The object may contain the following fields:
+
+ .. include:: presets/exclude-properties.rst
diff --git a/Help/manual/presets/fixtures-properties.rst b/Help/manual/presets/fixtures-properties.rst
new file mode 100644
index 0000000..727236a
--- /dev/null
+++ b/Help/manual/presets/fixtures-properties.rst
@@ -0,0 +1,27 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.filter.exclude.fixtures.any`:
+
+``any``
+ An optional string specifying a regex for text fixtures
+ to exclude from adding any tests. Equivalent to passing
+ :ctest-option:`--fixture-exclude-any` on the command
+ line. This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.filter.exclude.fixtures.setup`:
+
+``setup``
+ An optional string specifying a regex for text fixtures
+ to exclude from adding setup tests. Equivalent to
+ passing :ctest-option:`--fixture-exclude-setup` on the
+ command line. This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.filter.exclude.fixtures.cleanup`:
+
+``cleanup``
+ An optional string specifying a regex for text fixtures
+ to exclude from adding cleanup tests. Equivalent to
+ passing :ctest-option:`--fixture-exclude-cleanup` on
+ the command line.
+ This field supports `macro expansion`_.
diff --git a/Help/manual/presets/include-properties.rst b/Help/manual/presets/include-properties.rst
new file mode 100644
index 0000000..b55c0e1
--- /dev/null
+++ b/Help/manual/presets/include-properties.rst
@@ -0,0 +1,37 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.filter.include.name`:
+
+``name``
+ An optional string specifying a regex for test names.
+ Equivalent to passing :ctest-option:`--tests-regex` on the
+ command line. This field supports `macro expansion`_.
+
+ CMake regex syntax is described under
+ :ref:`string(REGEX) <Regex Specification>`.
+
+.. _`CMakePresets.testPresets.filter.include.label`:
+
+``label``
+ An optional string specifying a regex for test labels.
+ Equivalent to passing :ctest-option:`--label-regex` on the
+ command line. This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.filter.include.useUnion`:
+
+``useUnion``
+ An optional bool. Equivalent to passing
+ :ctest-option:`--union` on the command line.
+
+.. _`CMakePresets.testPresets.filter.include.index`:
+
+``index``
+ An optional object specifying tests to include by test
+ index. The object may contain the following fields. Can
+ also be an optional string specifying a file with the
+ command line syntax for
+ :ctest-option:`--tests-information`. If specified as a
+ string, this field supports `macro expansion`_.
+
+ .. include:: presets/index-properties.rst
diff --git a/Help/manual/presets/index-properties.rst b/Help/manual/presets/index-properties.rst
new file mode 100644
index 0000000..6bbce33
--- /dev/null
+++ b/Help/manual/presets/index-properties.rst
@@ -0,0 +1,22 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.filter.include.index.start`:
+
+``start``
+ An optional integer specifying a test index at which to start testing.
+
+.. _`CMakePresets.testPresets.filter.include.index.end`:
+
+``end``
+ An optional integer specifying a test index at which to stop testing.
+
+.. _`CMakePresets.testPresets.filter.include.index.stride`:
+
+``stride``
+ An optional integer specifying the increment.
+
+.. _`CMakePresets.testPresets.filter.include.index.specificTests`:
+
+``specificTests``
+ An optional array of integers specifying specific test indices to run.
diff --git a/Help/manual/presets/packageOutput-properties.rst b/Help/manual/presets/packageOutput-properties.rst
new file mode 100644
index 0000000..d8ab6fb
--- /dev/null
+++ b/Help/manual/presets/packageOutput-properties.rst
@@ -0,0 +1,16 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.packagePresets.output.debug`:
+
+``debug``
+ An optional boolean specifying whether or not to print debug
+ information. A value of ``true`` is equivalent to passing
+ :cpack-option:`--debug` on the command line.
+
+.. _`CMakePresets.packagePresets.output.verbose`:
+
+``verbose``
+ An optional boolean specifying whether or not to print
+ verbosely. A value of ``true`` is equivalent to passing
+ :cpack-option:`--verbose` on the command line.
diff --git a/Help/manual/presets/packagePresets-properties.rst b/Help/manual/presets/packagePresets-properties.rst
new file mode 100644
index 0000000..2c21b53
--- /dev/null
+++ b/Help/manual/presets/packagePresets-properties.rst
@@ -0,0 +1,174 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.packagePresets.name`:
+
+``name``
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the :option:`cpack --preset`
+ option. There must not be two package presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a package preset may have
+ the same name as a configure, build, test, or workflow preset.
+
+.. _`CMakePresets.packagePresets.hidden`:
+
+``hidden``
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :cpack-option:`--preset` argument and does not have to have a valid
+ ``configurePreset``, even from inheritance. ``hidden`` presets are
+ intended to be used as a base for other presets to inherit via the
+ ``inherits`` field.
+
+.. _`CMakePresets.packagePresets.inherits`:
+
+``inherits``
+ An optional array of strings representing the names of presets from which
+ to inherit. This field can also be a string, which is equivalent to an
+ array containing one string.
+
+ The preset will inherit all of the fields from the ``inherits`` presets
+ by default (except ``name``, ``hidden``, ``inherits``, ``description``,
+ and ``displayName``), but can override them as desired. If multiple
+ ``inherits`` presets provide conflicting values for the same field, the
+ earlier preset in the ``inherits`` array will be preferred.
+
+ A preset can only inherit from another preset that is defined in the same
+ file or in one of the files it includes (directly or indirectly). Presets
+ in ``CMakePresets.json`` may not inherit from presets in
+ ``CMakeUserPresets.json``.
+
+.. _`CMakePresets.packagePresets.condition`:
+
+``condition``
+ An optional `Condition`_ object.
+
+.. _`CMakePresets.packagePresets.vendor`:
+
+``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. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+.. _`CMakePresets.packagePresets.displayName`:
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
+
+.. _`CMakePresets.packagePresets.description`:
+
+``description``
+ An optional string with a human-friendly description of the preset.
+
+.. _`CMakePresets.packagePresets.environment`:
+
+``environment``
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or a
+ string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment.
+
+ This field supports `macro expansion`_, and environment variables in this
+ map may reference each other, and may be listed in any order, as long as
+ such references do not cause a cycle (for example, if ``ENV_1`` is
+ ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
+ allows one to prepend or append values to existing environment variables
+ by accessing only values from the parent environment.
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+.. _`CMakePresets.packagePresets.configurePreset`:
+
+``configurePreset``
+ An optional string specifying the name of a configure preset to
+ associate with this package preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset, so packaging will run in the same ``binaryDir``
+ that the configuration did and build did.
+
+.. _`CMakePresets.packagePresets.inheritConfigureEnvironment`:
+
+``inheritConfigureEnvironment``
+ An optional boolean that defaults to ``true``. If ``true``, the
+ environment variables from the associated configure preset are
+ inherited after all inherited package preset environments, but
+ before environment variables explicitly specified in this package
+ preset.
+
+.. _`CMakePresets.packagePresets.generators`:
+
+``generators``
+ An optional array of strings representing generators for CPack to use.
+
+.. _`CMakePresets.packagePresets.configurations`:
+
+``configurations``
+ An optional array of strings representing build configurations for CPack to package.
+
+.. _`CMakePresets.packagePresets.variables`:
+
+``variables``
+ An optional map of variables to pass to CPack, equivalent to
+ :cpack-option:`-D` arguments. Each key is the name of a variable,
+ and the value is the string to assign to that variable.
+
+.. _`CMakePresets.packagePresets.configFile`:
+
+``configFile``
+ An optional string representing the config file for CPack to use.
+
+.. _`CMakePresets.packagePresets.output`:
+
+``output``
+ An optional object specifying output options. Valid keys are:
+
+ .. include:: presets/packageOutput-properties.rst
+
+.. _`CMakePresets.packagePresets.packageName`:
+
+``packageName``
+ An optional string representing the package name.
+
+ .. note::
+
+ Due to problems with the implementation, this field does not affect
+ the name of the final package file produced. However, other aspects
+ of the package may use the value, leading to inconsistencies. A
+ future CMake release may address this problem, but until then, it
+ is recommended that this field not be used.
+
+
+.. _`CMakePresets.packagePresets.packageVersion`:
+
+``packageVersion``
+ An optional string representing the package version.
+
+ .. note::
+
+ Due to problems with the implementation, this field does not affect
+ the name of the final package file produced. However, other aspects
+ of the package may use the value, leading to inconsistencies. A
+ future CMake release may address this problem, but until then, it
+ is recommended that this field not be used.
+
+
+.. _`CMakePresets.packagePresets.packageDirectory`:
+
+``packageDirectory``
+ An optional string representing the directory in which to place the package.
+
+.. _`CMakePresets.packagePresets.vendorName`:
+
+``vendorName``
+ An optional string representing the vendor name.
diff --git a/Help/manual/presets/repeat-properties.rst b/Help/manual/presets/repeat-properties.rst
new file mode 100644
index 0000000..98800ff
--- /dev/null
+++ b/Help/manual/presets/repeat-properties.rst
@@ -0,0 +1,18 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.execution.repeat.mode`:
+
+``mode``
+ A required string. Must be one of the following values:
+
+ * ``until-fail``
+
+ * ``until-pass``
+
+ * ``after-timeout``
+
+.. _`CMakePresets.testPresets.execution.repeat.count`:
+
+``count``
+ A required integer.
diff --git a/Help/manual/presets/root-properties.rst b/Help/manual/presets/root-properties.rst
new file mode 100644
index 0000000..a1ccccb
--- /dev/null
+++ b/Help/manual/presets/root-properties.rst
@@ -0,0 +1,78 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.$schema`:
+
+``$schema``
+ .. presets-versionadded:: 8
+
+ An optional string that provides a URI to the JSON schema that describes the structure of this JSON document. This field is used for validation and autocompletion in editors that support JSON schema. It doesn't affect the behavior of the document itself. If this field is not specified, the JSON document will still be valid, but tools that use JSON schema for validation and autocompletion may not function correctly.
+
+.. _`CMakePresets.version`:
+
+``version``
+ A required integer representing the version of the JSON schema. See
+ `Versions`_ for discussion of the supported versions and the
+ corresponding version of CMake in which they were added.
+
+.. _`CMakePresets.cmakeMinimumRequired`:
+
+``cmakeMinimumRequired``
+ An optional object representing the minimum version of CMake
+ needed to build this project. This object consists of the following
+ fields:
+
+ .. include:: presets/cmakeMinimumRequired-properties.rst
+
+.. _`CMakePresets.include`:
+
+``include``
+ .. presets-versionadded:: 4
+
+ An optional array of strings representing files to include. If the
+ filenames are not absolute, they are considered relative to the current
+ file. See `Includes`_ for discussion of the constraints on included
+ files.
+
+.. _`CMakePresets.vendor`:
+
+``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, the keys should be a vendor-specific domain name
+ followed by a ``/``-separated path. For example, the Example IDE 1.0
+ could use ``example.com/ExampleIDE/1.0``. The value of each field can be
+ anything desired by the vendor, though will typically be a map.
+
+.. _`CMakePresets.configurePresets`:
+
+``configurePresets``
+ An optional array of `Configure Preset`_ objects.
+
+.. _`CMakePresets.buildPresets`:
+
+``buildPresets``
+ .. presets-versionadded:: 2
+
+ An optional array of `Build Preset`_ objects.
+
+.. _`CMakePresets.testPresets`:
+
+``testPresets``
+ .. presets-versionadded:: 2
+
+ An optional array of `Test Preset`_ objects.
+
+.. _`CMakePresets.packagePresets`:
+
+``packagePresets``
+ .. presets-versionadded:: 6
+
+ An optional array of `Package Preset`_ objects.
+
+.. _`CMakePresets.workflowPresets`:
+
+``workflowPresets``
+ .. presets-versionadded:: 6
+
+ An optional array of `Workflow Preset`_ objects.
diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json
index 6b60967..70f5024 100644
--- a/Help/manual/presets/schema.json
+++ b/Help/manual/presets/schema.json
@@ -1,184 +1,440 @@
{
"$schema": "http://json-schema.org/draft/2020-12/schema#",
"type": "object",
- "description": "The presets specify the generator and the build directory, and optionally a list of variables and other arguments to pass to CMake.",
"oneOf": [
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 1,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 1
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV1" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v1..v2"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 2,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 2
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV1" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV2" },
- "testPresets": { "$ref": "#/definitions/testPresetsV2" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v1..v2"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v2"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v2"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 3,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 3
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV3" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV3" },
- "testPresets": { "$ref": "#/definitions/testPresetsV3" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v3..v6"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v3"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v3..v4"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 4,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 4
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV3" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV4" },
- "testPresets": { "$ref": "#/definitions/testPresetsV3" },
- "include": { "$ref": "#/definitions/include" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v3..v6"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v4..v9"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v3..v4"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 5,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 5
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV3" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV4" },
- "testPresets": { "$ref": "#/definitions/testPresetsV5" },
- "include": { "$ref": "#/definitions/include" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v3..v6"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v4..v9"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v5"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 6,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 6
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV3" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV4" },
- "testPresets": { "$ref": "#/definitions/testPresetsV6" },
- "packagePresets": { "$ref": "#/definitions/packagePresetsV6" },
- "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" },
- "include": { "$ref": "#/definitions/include" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v3..v6"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v4..v9"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v6..v9"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v6..v9"
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v6..v9"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
"version": {
- "const": 7,
- "description": "A required integer representing the version of the JSON schema."
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 7
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV7" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV4" },
- "testPresets": { "$ref": "#/definitions/testPresetsV6" },
- "packagePresets": { "$ref": "#/definitions/packagePresetsV6" },
- "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" },
- "include": { "$ref": "#/definitions/include" }
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v7..v9"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v4..v9"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v6..v9"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v6..v9"
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v6..v9"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
- "$schema": { "$ref": "#/definitions/$schema" },
- "version": {
- "const": 8,
- "description": "A required integer representing the version of the JSON schema."
+ "$schema": {
+ "$ref": "#/definitions/$schema@v8.."
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV7" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV4" },
- "testPresets": { "$ref": "#/definitions/testPresetsV6" },
- "packagePresets": { "$ref": "#/definitions/packagePresetsV6" },
- "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" },
- "include": { "$ref": "#/definitions/include" }
+ "version": {
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 8
+ },
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v7..v9"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v4..v9"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v6..v9"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v6..v9"
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v6..v9"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
- "$schema": { "$ref": "#/definitions/$schema" },
- "version": {
- "const": 9,
- "description": "A required integer representing the version of the JSON schema."
+ "$schema": {
+ "$ref": "#/definitions/$schema@v8.."
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV1" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV7" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV4" },
- "testPresets": { "$ref": "#/definitions/testPresetsV6" },
- "packagePresets": { "$ref": "#/definitions/packagePresetsV6" },
- "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" },
- "include": { "$ref": "#/definitions/include" }
+ "version": {
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 9
+ },
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v1..v9"
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v7..v9"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v4..v9"
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v6..v9"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v6..v9"
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v6..v9"
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
- "$schema": { "$ref": "#/definitions/$schema" },
- "$comment": { "$ref": "#/definitions/$comment" },
- "version": {
- "const": 10,
- "description": "A required integer representing the version of the JSON schema."
+ "$schema": {
+ "$ref": "#/definitions/$schema@v8.."
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV10" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV10" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV10" },
- "testPresets": { "$ref": "#/definitions/testPresetsV10" },
- "packagePresets": { "$ref": "#/definitions/packagePresetsV10" },
- "workflowPresets": { "$ref": "#/definitions/workflowPresetsV10" },
- "include": { "$ref": "#/definitions/include" }
+ "version": {
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 10
+ },
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v10.."
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v10..v11"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v10.."
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v10"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v10.."
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
},
+ "required": [
+ "version"
+ ],
"additionalProperties": false
},
{
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
"properties": {
- "$schema": { "$ref": "#/definitions/$schema" },
- "$comment": { "$ref": "#/definitions/$comment" },
- "version": {
- "const": 11,
- "description": "A required integer representing the version of the JSON schema."
+ "$schema": {
+ "$ref": "#/definitions/$schema@v8.."
},
- "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequiredV10" },
- "vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresetsV10" },
- "buildPresets": { "$ref": "#/definitions/buildPresetsV10" },
- "testPresets": { "$ref": "#/definitions/testPresetsV11" },
- "packagePresets": { "$ref": "#/definitions/packagePresetsV10" },
- "workflowPresets": { "$ref": "#/definitions/workflowPresetsV10" },
- "include": { "$ref": "#/definitions/include" }
+ "version": {
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 11
+ },
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v10.."
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v10..v11"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v10.."
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v11"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v10.."
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
},
+ "required": [
+ "version"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "description": "The presets specify the generator and the build directory, and optionally an array of variables and other arguments to pass to CMake.",
+ "properties": {
+ "$schema": {
+ "$ref": "#/definitions/$schema@v8.."
+ },
+ "version": {
+ "type": "integer",
+ "description": "A required integer representing the version of the JSON schema.",
+ "const": 12
+ },
+ "cmakeMinimumRequired": {
+ "$ref": "#/definitions/cmakeMinimumRequired@v10.."
+ },
+ "include": {
+ "$ref": "#/definitions/include@v4.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/vendor@v1.."
+ },
+ "configurePresets": {
+ "$ref": "#/definitions/configurePresets@v12"
+ },
+ "buildPresets": {
+ "$ref": "#/definitions/buildPresets@v10.."
+ },
+ "testPresets": {
+ "$ref": "#/definitions/testPresets@v12"
+ },
+ "packagePresets": {
+ "$ref": "#/definitions/packagePresets@v10.."
+ },
+ "workflowPresets": {
+ "$ref": "#/definitions/workflowPresets@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "version"
+ ],
"additionalProperties": false
}
],
@@ -186,1945 +442,3571 @@
"version"
],
"definitions": {
- "$schema": {
+ "$schema@v8..": {
"type": "string",
- "description": "The schema against which to verify this document.",
- "format": "uri-reference"
+ "format": "uri-reference",
+ "description": "An optional string that provides a URI to the JSON schema that describes the structure of this JSON document. This field is used for validation and autocompletion in editors that support JSON schema. It doesn't affect the behavior of the document itself. If this field is not specified, the JSON document will still be valid, but tools that use JSON schema for validation and autocompletion may not function correctly."
},
- "$comment": {
+ "cmakeMinimumRequired@v1..v9": {
+ "type": "object",
+ "description": "An optional object representing the minimum version of CMake needed to build this project.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "major": {
+ "$ref": "#/definitions/cmakeMinimumRequired.major@v1.."
+ },
+ "minor": {
+ "$ref": "#/definitions/cmakeMinimumRequired.minor@v1.."
+ },
+ "patch": {
+ "$ref": "#/definitions/cmakeMinimumRequired.patch@v1.."
+ }
+ }
+ },
+ "cmakeMinimumRequired@v10..": {
+ "type": "object",
+ "description": "An optional object representing the minimum version of CMake needed to build this project.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "major": {
+ "$ref": "#/definitions/cmakeMinimumRequired.major@v1.."
+ },
+ "minor": {
+ "$ref": "#/definitions/cmakeMinimumRequired.minor@v1.."
+ },
+ "patch": {
+ "$ref": "#/definitions/cmakeMinimumRequired.patch@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "cmakeMinimumRequired.major@v1..": {
+ "type": "integer",
+ "description": "An optional integer representing the major version."
+ },
+ "cmakeMinimumRequired.minor@v1..": {
+ "type": "integer",
+ "description": "An optional integer representing the minor version."
+ },
+ "cmakeMinimumRequired.patch@v1..": {
+ "type": "integer",
+ "description": "An optional integer representing the patch version."
+ },
+ "$comment@v10..": {
+ "$ref": "#/definitions/comment@v10.."
+ },
+ "comment@v10..": {
"anyOf": [
{
"type": "string",
- "description": "The single-line comment"
+ "description": "A single-line comment."
},
{
"type": "array",
- "description": "The multi-line comment",
+ "description": "A multi-line comment.",
"minItems": 1,
"items": {
"type": "string",
- "description": "One line of the multi-line comment"
+ "description": "One line of the multi-line comment."
}
}
]
},
- "commonPropertiesAll": {
- "properties": {
- "name": {
- "type": "string",
- "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
- "minLength": 1
- },
- "vendor": {
- "type": "object",
- "description": "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.",
- "properties": {}
- },
- "displayName": {
- "type": "string",
- "description": "An optional string with a human-friendly name of the preset."
- },
- "description": {
- "type": "string",
- "description": "An optional string with a human-friendly description of the preset."
- }
- }
- },
- "configureBuildTestPackagePresetsEnvironmentProperty": {
- "properties": {
- "environment": {
- "type": "object",
- "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
- "properties": {},
- "additionalProperties": {
- "anyOf": [
- {
- "type": "null",
- "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
- },
- {
- "type": "string",
- "description": "A string representing the value of the variable."
- }
- ]
- },
- "propertyNames": {
- "pattern": "^.+$"
- }
- }
- }
- },
- "commentAsProperty": {
- "properties": {
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- },
- "cmakeMinimumRequiredObject": {
- "properties": {
- "major": {
- "type": "integer",
- "description": "An optional integer representing the major version."
- },
- "minor": {
- "type": "integer",
- "description": "An optional integer representing the minor version."
- },
- "patch": {
- "type": "integer",
- "description": "An optional integer representing the patch version."
- }
- }
- },
- "cmakeMinimumRequiredV10": {
- "type": "object",
- "description": "An optional object representing the minimum version of CMake needed to build this project. Available in version 10 and higher.",
- "allOf": [
- { "$ref": "#/definitions/cmakeMinimumRequiredObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "cmakeMinimumRequiredV1": {
- "type": "object",
- "description": "An optional object representing the minimum version of CMake needed to build this project. Available in version 1 and higher.",
- "allOf": [
- { "$ref": "#/definitions/cmakeMinimumRequiredObject" }
- ],
- "unevaluatedProperties": false
- },
- "vendor": {
- "type": "object",
- "description": "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, the keys should be a vendor-specific domain name followed by a /-separated path. For example, the Example IDE 1.0 could use example.com/ExampleIDE/1.0. The value of each field can be anything desired by the vendor, though will typically be a map.",
- "properties": {}
- },
- "configurePresetsArchitectureAsStringV1": {
- "type": "string",
- "description": "An optional string representing the platform for generators that support it."
- },
- "configurePresetsArchitectureAsObjectV1": {
- "properties": {
- "value": {
- "type": "string",
- "description": "An optional string representing the value."
- },
- "strategy": {
- "type": "string",
- "description": "An optional string telling CMake how to handle the field. Valid values are: \"set\" Set the respective value. This will result in an error for generators that do not support the respective field. \"external\" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake.",
- "enum": [
- "set",
- "external"
- ]
- }
- }
- },
- "configurePresetsArchitectureV10": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsArchitectureAsStringV1" },
- {
- "type": "object",
- "description": "An optional object representing the platform for generators that support it. Available in version 10 and higher.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsArchitectureAsObjectV1" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "configurePresetsArchitectureV1": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsArchitectureAsStringV1" },
- {
- "type": "object",
- "description": "An optional object representing the platform for generators that support it. Available in version 1 and higher.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsArchitectureAsObjectV1" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "configurePresetsToolsetAsStringV1": {
- "type": "string",
- "description": "An optional string representing the toolset for generators that support it."
- },
- "configurePresetsToolsetAsObjectV1": {
- "properties": {
- "value": {
- "type": "string",
- "description": "An optional string representing the value."
- },
- "strategy": {
- "type": "string",
- "description": "An optional string telling CMake how to handle the field. Valid values are: \"set\" Set the respective value. This will result in an error for generators that do not support the respective field. \"external\" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake.",
- "enum": [
- "set",
- "external"
- ]
- }
- }
- },
- "configurePresetsToolsetV10": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsToolsetAsStringV1" },
- {
- "type": "object",
- "description": "An optional object representing the toolset for generators that support it. Available in version 10 and higher.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsToolsetAsObjectV1" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "configurePresetsToolsetV1": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsToolsetAsStringV1" },
- {
- "type": "object",
- "description": "An optional object representing the toolset for generators that support it. Available in version 1 and higher.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsToolsetAsObjectV1" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "configurePresetsCacheVariablesAdditionalPropertiesAsNull": {
- "type": "null",
- "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
- },
- "configurePresetsCacheVariablesAdditionalPropertiesAsBoolean": {
- "type": "boolean",
- "description": "A boolean representing the value of the variable. Equivalent to \"TRUE\" or \"FALSE\"."
- },
- "configurePresetsCacheVariablesAdditionalPropertiesAsString": {
- "type": "string",
- "description": "A string representing the value of the variable (which supports macro expansion)."
- },
- "configurePresetsCacheVariablesAdditionalPropertiesAsObject": {
- "properties": {
- "type": {
- "type": "string",
- "description": "An optional string representing the type of the variable. It should be BOOL, FILEPATH, PATH, STRING, or INTERNAL.",
- "enum": [
- "BOOL", "FILEPATH", "PATH", "STRING", "INTERNAL"
- ]
- },
- "value": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsBoolean" },
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsString" }
- ]
- }
- },
- "required": [
- "value"
- ]
- },
- "configurePresetsCacheVariablesAdditionalPropertiesV10": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsNull" },
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsBoolean" },
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsString" },
- {
- "type": "object",
- "description": "An optional object representing the cache variables for generators that support it. Available in version 10 and higher.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "configurePresetsCacheVariablesAdditionalPropertiesV1": {
- "anyOf": [
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsNull" },
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsBoolean" },
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsString" },
- {
- "type": "object",
- "description": "An optional object representing the cache variables for generators that support it. Available in version 1 and higher.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesAsObject" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "configurePresetsTraceV10": {
- "type": "object",
- "description": "An optional object specifying trace options.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsTraceObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsTraceV7": {
- "type": "object",
- "description": "An optional object specifying trace options.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsTraceObject" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsTraceObject": {
- "properties": {
- "mode": {
- "type": "string",
- "description": "An optional string that specifies the trace mode.",
- "enum": [
- "on", "off", "expand"
- ]
- },
- "format": {
- "type": "string",
- "description": "An optional string that specifies the trace output format.",
- "enum": [
- "human", "json-v1"
- ]
- },
- "source": {
- "anyOf": [
- {
- "type": "string",
- "description": "An optional string representing the path to one source file to be traced.",
- "minLength": 1
- },
- {
- "type": "array",
- "description": "An optional array of strings representing the paths to source files to be traced.",
- "items": {
- "type": "string",
- "description": "A string representing the path to one source file to be traced.",
- "minLength": 1
- }
- }
- ]
- },
- "redirect": {
- "type": "string",
- "description": "An optional string specifying a path to a trace output file."
- }
- }
- },
- "configurePresetsDebugV10": {
- "type": "object",
- "description": "An optional object specifying debug options.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsDebugObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsDebugV1": {
- "type": "object",
- "description": "An optional object specifying debug options.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsDebugObject" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsErrorsV10": {
- "type": "object",
- "description": "An optional object specifying errors.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsErrorsObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsErrorsV1": {
- "type": "object",
- "description": "An optional object specifying errors.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsErrorsObject" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsWarningsV10": {
- "type": "object",
- "description": "An optional object specifying warnings.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsWarningsObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsWarningsV1": {
- "type": "object",
- "description": "An optional object specifying warnings.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsWarningsObject" }
- ],
- "unevaluatedProperties": false
- },
- "configurePresetsDebugObject": {
- "properties": {
- "output": {
- "type": "boolean",
- "description": "An optional boolean. Setting this to true is equivalent to passing --debug-output on the command line."
- },
- "tryCompile": {
- "type": "boolean",
- "description": "An optional boolean. Setting this to true is equivalent to passing --debug-trycompile on the command line."
- },
- "find": {
- "type": "boolean",
- "description": "An optional boolean. Setting this to true is equivalent to passing --debug-find on the command line."
- }
- }
- },
- "configurePresetsErrorsObject": {
- "properties": {
- "dev": {
- "type": "boolean",
- "description": "An optional boolean. Equivalent to passing -Werror=dev or -Wno-error=dev on the command line. This may not be set to true if warnings.dev is set to false."
- },
- "deprecated": {
- "type": "boolean",
- "description": "An optional boolean. Equivalent to passing -Werror=deprecated or -Wno-error=deprecated on the command line. This may not be set to true if warnings.deprecated is set to false."
- }
- }
- },
- "configurePresetsWarningsObject": {
- "properties": {
- "dev": {
- "type": "boolean",
- "description": "An optional boolean. Equivalent to passing -Wdev or -Wno-dev on the command line. This may not be set to false if errors.dev is set to true."
- },
- "deprecated": {
- "type": "boolean",
- "description": "An optional boolean. Equivalent to passing -Wdeprecated or -Wno-deprecated on the command line. This may not be set to false if errors.deprecated is set to true."
- },
- "uninitialized": {
- "type": "boolean",
- "description": "An optional boolean. Setting this to true is equivalent to passing --warn-uninitialized on the command line."
- },
- "unusedCli": {
- "type": "boolean",
- "description": "An optional boolean. Setting this to false is equivalent to passing --no-warn-unused-cli on the command line."
- },
- "systemVars": {
- "type": "boolean",
- "description": "An optional boolean. Setting this to true is equivalent to passing --check-system-vars on the command line."
- }
- }
- },
- "configurePresetsItemsV10": {
- "properties": {
- "graphviz": {
- "type": "string",
- "description": "An optional string specifying the path to graphviz dot file. Available in version 10 and higher."
- }
- }
- },
- "configurePresetsItemsV3": {
- "properties": {
- "toolchainFile": {
- "type": "string",
- "description": "An optional string representing the path to the toolchain file. This field supports macro expansion. If a relative path is specified, it is calculated relative to the build directory, and if not found, relative to the source directory."
- },
- "installDir": {
- "type": "string",
- "description": "An optional string representing the path to the installation directory, which will be used as the CMAKE_INSTALL_PREFIX variable. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory."
- }
- }
- },
- "configurePresetsItemsV1": {
- "allOf": [
- { "$ref": "#/definitions/commonPropertiesAll" },
- { "$ref": "#/definitions/configureBuildTestPackagePresetsEnvironmentProperty" },
- {
- "properties": {
- "hidden": {
- "type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset= argument, will not show up in the CMake GUI, and does not have to have a valid generator or binaryDir, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
- },
- "inherits": {
- "anyOf": [
- {
- "type": "string",
- "description": "An optional string representing the name of the preset to inherit from.",
- "minLength": 1
- },
- {
- "type": "array",
- "description": "An optional array of strings representing the names of presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
- "items": {
- "type": "string",
- "description": "An optional string representing the name of the preset to inherit from.",
- "minLength": 1
- }
- }
- ]
- },
- "cmakeExecutable": {
- "type": "string",
- "description": "An optional string representing the path to the CMake executable to use for this preset. This is reserved for use by IDEs, and is not used by CMake itself. IDEs that use this field should expand any macros in it."
- }
- }
- }
- ],
- "required": [
- "name"
- ]
- },
- "configurePresetsAdditionalPropertiesV10": {
- "properties": {
- "toolset": { "$ref": "#/definitions/configurePresetsToolsetV10" },
- "architecture": { "$ref": "#/definitions/configurePresetsArchitectureV10" },
- "cacheVariables": {
- "type": "object",
- "description": "An optional map of cache variables. The key is the variable name (which must not be an empty string). Cache variables are inherited through the inherits field, and the preset's variables will be the union of its own cacheVariables and the cacheVariables from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied.",
- "properties": {},
- "propertyNames": {
- "pattern": "^.+$"
- },
- "additionalProperties": { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesV10" }
- },
- "binaryDir": {
- "type": "string",
- "description": "An optional string representing the path to the output binary directory. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory. If binaryDir is not specified, the path is calculated using regular methods."
- },
- "generator": {
- "type": "string",
- "description": "An optional string representing the generator to use for the preset. If generator is not specified, the normal generator discovery procedure is used. Note that for Visual Studio generators, unlike in the command line -G argument, you cannot include the platform name in the generator name. Use the architecture field instead."
- },
- "condition": { "$ref": "#/definitions/topConditionV10" },
- "warnings": { "$ref": "#/definitions/configurePresetsWarningsV10" },
- "errors": { "$ref": "#/definitions/configurePresetsErrorsV10" },
- "debug": { "$ref": "#/definitions/configurePresetsDebugV10" },
- "trace": { "$ref": "#/definitions/configurePresetsTraceV10" }
- }
- },
- "configurePresetsAdditionalPropertiesV7": {
- "allOf": [
- { "$ref": "#/definitions/configurePresetsAdditionalPropertiesV3" },
- {
- "properties": {
- "trace": { "$ref": "#/definitions/configurePresetsTraceV7" }
- }
- }
- ]
- },
- "configurePresetsAdditionalPropertiesV3": {
- "allOf": [
- { "$ref": "#/definitions/configurePresetsAdditionalPropertiesV1" },
- {
- "properties": {
- "condition": { "$ref": "#/definitions/topConditionV3" },
- "binaryDir": {
- "type": "string",
- "description": "An optional string representing the path to the output binary directory. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory. If binaryDir is not specified, the path is calculated using regular methods."
- },
- "generator": {
- "type": "string",
- "description": "An optional string representing the generator to use for the preset. If generator is not specified, the normal generator discovery procedure is used. Note that for Visual Studio generators, unlike in the command line -G argument, you cannot include the platform name in the generator name. Use the architecture field instead."
- }
- }
- }
- ]
- },
- "configurePresetsAdditionalPropertiesV1": {
- "properties": {
- "toolset": { "$ref": "#/definitions/configurePresetsToolsetV1" },
- "architecture": { "$ref": "#/definitions/configurePresetsArchitectureV1" },
- "cacheVariables": {
- "type": "object",
- "description": "An optional map of cache variables. The key is the variable name (which must not be an empty string). Cache variables are inherited through the inherits field, and the preset's variables will be the union of its own cacheVariables and the cacheVariables from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied.",
- "properties": {},
- "propertyNames": {
- "pattern": "^.+$"
- },
- "additionalProperties": { "$ref": "#/definitions/configurePresetsCacheVariablesAdditionalPropertiesV1" }
- },
- "binaryDir": {
- "type": "string",
- "description": "An optional string representing the path to the output binary directory. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory. If binaryDir is not specified, it must be inherited from the inherits preset (unless this preset is hidden)."
- },
- "generator": {
- "type": "string",
- "description": "An optional string representing the generator to use for the preset. If generator is not specified, it must be inherited from the inherits preset (unless this preset is hidden). Note that for Visual Studio generators, unlike in the command line -G argument, you cannot include the platform name in the generator name. Use the architecture field instead."
- },
- "warnings": { "$ref": "#/definitions/configurePresetsWarningsV1" },
- "errors": { "$ref": "#/definitions/configurePresetsErrorsV1" },
- "debug": { "$ref": "#/definitions/configurePresetsDebugV1" }
- }
- },
- "configurePresetsV10": {
- "type": "array",
- "description": "An optional array of configure preset objects. Available in version 10 and higher.",
- "items": {
- "type": "object",
- "description": "A configure preset object.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsItemsV10" },
- { "$ref": "#/definitions/configurePresetsItemsV3" },
- { "$ref": "#/definitions/configurePresetsItemsV1" },
- { "$ref": "#/definitions/configurePresetsAdditionalPropertiesV10" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- },
- "configurePresetsV7": {
- "type": "array",
- "description": "An optional array of configure preset objects. Available in version 7 and higher.",
- "items": {
- "type": "object",
- "description": "A configure preset object.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsItemsV3" },
- { "$ref": "#/definitions/configurePresetsItemsV1" },
- { "$ref": "#/definitions/configurePresetsAdditionalPropertiesV7" }
- ],
- "unevaluatedProperties": false
- }
- },
- "configurePresetsV3": {
- "type": "array",
- "description": "An optional array of configure preset objects. Available in version 3 and higher.",
- "items": {
- "type": "object",
- "description": "A configure preset object.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsItemsV3" },
- { "$ref": "#/definitions/configurePresetsItemsV1" },
- { "$ref": "#/definitions/configurePresetsAdditionalPropertiesV3" }
- ],
- "unevaluatedProperties": false
- }
- },
- "configurePresetsV1": {
- "type": "array",
- "description": "An optional array of configure preset objects. Available in version 1 and higher.",
- "items": {
- "type": "object",
- "description": "A configure preset object.",
- "allOf": [
- { "$ref": "#/definitions/configurePresetsItemsV1" },
- { "$ref": "#/definitions/configurePresetsAdditionalPropertiesV1" }
- ],
- "unevaluatedProperties": false
- }
- },
- "buildPresetsItemsV4": {
- "properties": {
- "resolvePackageReferences": {
- "type": "string",
- "description": "An optional string specifying the package resolve behavior. Valid values are \"on\" (packages are resolved prior to the build), \"off\" (packages are not resolved prior to the build), and \"only\" (packages are resolved, but no build will be performed).",
- "enum": [
- "on", "off", "only"
- ]
- }
- }
- },
- "buildPresetsItemsV2": {
- "allOf": [
- { "$ref": "#/definitions/commonPropertiesAll" },
- { "$ref": "#/definitions/configureBuildTestPackagePresetsEnvironmentProperty" },
- {
- "properties": {
- "hidden": {
- "type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
- },
- "inherits": {
- "anyOf": [
- {
- "type": "string",
- "description": "An optional string representing the name of the build preset to inherit from.",
- "minLength": 1
- },
- {
- "type": "array",
- "description": "An optional array of strings representing the names of build presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
- "items": {
- "type": "string",
- "description": "An optional string representing the name of the preset to inherit from.",
- "minLength": 1
- }
- }
- ]
- },
- "configurePreset": {
- "type": "string",
- "description": "An optional string specifying the name of a configure preset to associate with this build preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.",
- "minLength": 1
- },
- "inheritConfigureEnvironment": {
- "type": "boolean",
- "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited build preset environments, but before environment variables explicitly specified in this build preset."
- },
- "jobs": {
- "type": "integer",
- "description": "An optional non-negative integer. Equivalent to passing --parallel or -j on the command line.",
- "minimum": 0
- },
- "targets": {
- "anyOf": [
- {
- "type": "string",
- "description": "An optional string. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets."
- },
- {
- "type": "array",
- "description": "An optional array of strings. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets.",
- "items": {
- "type": "string",
- "description": "An optional string. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets."
- }
- }
- ]
- },
- "configuration": {
- "type": "string",
- "description": "An optional string. Equivalent to passing --config on the command line."
- },
- "cleanFirst": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --clean-first on the command line."
- },
- "verbose": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --verbose on the command line."
- },
- "nativeToolOptions": {
- "type": "array",
- "description": "An optional array of strings. Equivalent to passing options after -- on the command line.",
- "items": {
- "type": "string",
- "description": "An optional string representing an option to pass after -- on the command line."
- }
- }
- }
- }
- ],
- "required": [
- "name"
- ]
- },
- "buildPresetsAdditionalPropertiesV10": {
- "properties": {
- "condition": { "$ref": "#/definitions/topConditionV10" }
- }
- },
- "buildPresetsAdditionalPropertiesV3": {
- "properties": {
- "condition": { "$ref": "#/definitions/topConditionV3" }
- }
- },
- "buildPresetsV10": {
- "type": "array",
- "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 10 and higher.",
- "items": {
- "type": "object",
- "description": "A build preset object.",
- "allOf": [
- { "$ref": "#/definitions/buildPresetsItemsV4" },
- { "$ref": "#/definitions/buildPresetsItemsV2" },
- { "$ref": "#/definitions/buildPresetsAdditionalPropertiesV10" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- },
- "buildPresetsV4": {
- "type": "array",
- "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 4 and higher.",
- "items": {
- "type": "object",
- "description": "A build preset object.",
- "allOf": [
- { "$ref": "#/definitions/buildPresetsItemsV4" },
- { "$ref": "#/definitions/buildPresetsItemsV2" },
- { "$ref": "#/definitions/buildPresetsAdditionalPropertiesV3" }
- ],
- "unevaluatedProperties": false
- }
- },
- "buildPresetsV3": {
- "type": "array",
- "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 3 and higher.",
- "items": {
- "type": "object",
- "description": "A build preset object.",
- "allOf": [
- { "$ref": "#/definitions/buildPresetsItemsV2" },
- { "$ref": "#/definitions/buildPresetsAdditionalPropertiesV3" }
- ],
- "unevaluatedProperties": false
- }
- },
- "buildPresetsV2": {
- "type": "array",
- "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.",
- "items": {
- "type": "object",
- "description": "A build preset object.",
- "allOf": [
- { "$ref": "#/definitions/buildPresetsItemsV2" }
- ],
- "unevaluatedProperties": false
- }
- },
- "testPresetsExecutionJobsV11": {
- "oneOf": [
- {
- "type": "integer",
- "description": "An optional non-negative integer. Equivalent to passing --parallel or -j on the command line.",
- "minimum": 0
- },
- {
- "type": "string",
- "description": "An optional string. Equivalent to passing --parallel or -j on the command line with the number of jobs omitted.",
- "minLength": 0,
- "maxLength": 0
- }
- ]
- },
- "testPresetsExecutionJobsV2": {
- "type": "integer",
- "description": "An optional non-negative integer. Equivalent to passing --parallel or -j on the command line.",
- "minimum": 0
- },
- "testPresetsExecutionRepeatV10": {
- "type": "object",
- "description": "An optional object specifying how to repeat tests. Equivalent to passing --repeat on the command line.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsExecutionRepeatObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsExecutionRepeatV2": {
- "type": "object",
- "description": "An optional object specifying how to repeat tests. Equivalent to passing --repeat on the command line.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsExecutionRepeatObject" }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsExecutionRepeatObject": {
- "properties": {
- "mode": {
- "type": "string",
- "description": "A required string. Must be one of the following values: \"until-fail\", \"until-pass\", or \"after-timeout\".",
- "enum": [
- "until-fail", "until-pass", "after-timeout"
- ]
- },
- "count": {
- "type": "integer",
- "description": "A required integer."
- }
- },
- "required": [
- "mode", "count"
- ]
- },
- "testPresetsFilterIncludeIndexAsStringV2": {
- "type": "string",
- "description": "An optional string specifying a file with the command line syntax for --tests-information. Available in version 2 and higher."
- },
- "testPresetsFilterIncludeIndexAsObjectV10": {
- "type": "object",
- "description": "An optional object specifying tests to include by test index. Available in version 10 and higher.",
- "properties": {
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- },
- "testPresetsFilterIncludeIndexAsObjectV2": {
- "type": "object",
- "description": "An optional object specifying tests to include by test index. Available in version 2 and higher.",
- "properties": {
- "start": {
- "type": "integer",
- "description": "An optional integer specifying a test index to start testing at."
- },
- "end": {
- "type": "integer",
- "description": "An optional integer specifying a test index to stop testing at."
- },
- "stride": {
- "type": "integer",
- "description": "An optional integer specifying the increment."
- },
- "specificTests": {
- "type": "array",
- "description": "An optional array of integers specifying specific test indices to run.",
- "items": {
- "type": "integer",
- "description": "An integer specifying the test to run by index."
- }
- }
- }
- },
- "testPresetsFilterIncludeIndexV10": {
- "anyOf": [
- { "$ref": "#/definitions/testPresetsFilterIncludeIndexAsStringV2" },
- {
- "type": "object",
- "description": "An optional object specifying test preset filters. Available in version 10 and higher.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterIncludeIndexAsObjectV2" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "testPresetsFilterIncludeIndexV2": {
- "anyOf": [
- { "$ref": "#/definitions/testPresetsFilterIncludeIndexAsStringV2" },
- {
- "type": "object",
- "description": "An optional object specifying test preset filters. Available in version 2 and higher.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterIncludeIndexAsObjectV2" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "testPresetsFilterIncludeV10": {
- "type": "object",
- "description": "An optional object specifying which tests to include.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterIncludeObject" },
- { "$ref": "#/definitions/commentAsProperty" },
- {
- "properties": {
- "index": { "$ref": "#/definitions/testPresetsFilterIncludeIndexV10" }
- }
- }
- ]
- },
- "testPresetsFilterIncludeV2": {
- "type": "object",
- "description": "An optional object specifying which tests to include.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterIncludeObject" },
- {
- "properties": {
- "index": { "$ref": "#/definitions/testPresetsFilterIncludeIndexV2" }
- }
- }
- ]
- },
- "testPresetsFilterIncludeObject": {
- "properties": {
- "name": {
- "type": "string",
- "description": "An optional string specifying a regex for test names. Equivalent to passing --tests-regex on the command line."
- },
- "label": {
- "type": "string",
- "description": "An optional string specifying a regex for test labels. Equivalent to passing --label-regex on the command line."
- },
- "useUnion": {
- "type": "boolean",
- "description": "An optional boolean. Equivalent to passing --union on the command line."
- }
- }
- },
- "testPresetsFilterExcludeV10": {
- "type": "object",
- "description": "An optional object specifying which tests to exclude.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterExcludeObject" },
- { "$ref": "#/definitions/commentAsProperty" },
- {
- "properties": {
- "fixtures": {
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterExcludeFixturesV2" },
- { "$ref": "#/definitions/commentAsProperty" }
- ]
- }
- }
- }
- ]
- },
- "testPresetsFilterExcludeV2": {
- "type": "object",
- "description": "An optional object specifying which tests to exclude.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsFilterExcludeObject" },
- {
- "properties": {
- "fixtures": { "$ref": "#/definitions/testPresetsFilterExcludeFixturesV2" }
- }
- }
- ]
- },
- "testPresetsFilterExcludeFixturesV2": {
- "type": "object",
- "description": "An optional object specifying which fixtures to exclude from adding tests.",
- "properties": {
- "any": {
- "type": "string",
- "description": "An optional string specifying a regex for text fixtures to exclude from adding any tests. Equivalent to --fixture-exclude-any on the command line."
- },
- "setup": {
- "type": "string",
- "description": "An optional string specifying a regex for text fixtures to exclude from adding setup tests. Equivalent to --fixture-exclude-setup on the command line."
- },
- "cleanup": {
- "type": "string",
- "description": "An optional string specifying a regex for text fixtures to exclude from adding cleanup tests. Equivalent to --fixture-exclude-cleanup on the command line."
- }
- }
- },
- "testPresetsFilterExcludeObject": {
- "properties": {
- "name": {
- "type": "string",
- "description": "An optional string specifying a regex for test names. Equivalent to passing --exclude-regex on the command line."
- },
- "label": {
- "type": "string",
- "description": "An optional string specifying a regex for test labels. Equivalent to passing --label-exclude on the command line."
- }
- }
- },
- "testPresetsExecutionV11": {
- "type": "object",
- "description": "An optional object specifying options for test execution.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsExecutionObject" },
- { "$ref": "#/definitions/commentAsProperty" },
- {
- "properties": {
- "repeat": { "$ref": "#/definitions/testPresetsExecutionRepeatV10" },
- "jobs": { "$ref": "#/definitions/testPresetsExecutionJobsV11" }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsExecutionV10": {
- "type": "object",
- "description": "An optional object specifying options for test execution.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsExecutionObject" },
- { "$ref": "#/definitions/commentAsProperty" },
- {
- "properties": {
- "repeat": { "$ref": "#/definitions/testPresetsExecutionRepeatV10" },
- "jobs": { "$ref": "#/definitions/testPresetsExecutionJobsV2" }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsExecutionV2": {
- "type": "object",
- "description": "An optional object specifying options for test execution.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsExecutionObject" },
- {
- "properties": {
- "repeat": { "$ref": "#/definitions/testPresetsExecutionRepeatV2" },
- "jobs": { "$ref": "#/definitions/testPresetsExecutionJobsV2" }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsExecutionObject": {
- "properties": {
- "stopOnFailure": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --stop-on-failure on the command line."
- },
- "enableFailover": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing -F on the command line."
- },
- "resourceSpecFile": {
- "type": "string",
- "description": "An optional string. Equivalent to passing --resource-spec-file on the command line."
- },
- "testLoad": {
- "type": "integer",
- "description": "An optional integer. Equivalent to passing --test-load on the command line."
- },
- "showOnly": {
- "type": "string",
- "description": "An optional string. Equivalent to passing --show-only on the command line. Value must be \"human\" or \"json-v1\".",
- "enum": [
- "human", "json-v1"
- ]
- },
- "interactiveDebugging": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --interactive-debug-mode 1 on the command line. If false, equivalent to passing --interactive-debug-mode 0 on the command line."
- },
- "scheduleRandom": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --schedule-random on the command line."
- },
- "timeout": {
- "type": "integer",
- "description": "An optional integer. Equivalent to passing --timeout on the command line."
- },
- "noTestsAction": {
- "type": "string",
- "description": "An optional string specifying the behavior if no tests are found. Must be one of the following values: \"default\" (equivalent to not passing any value on the command line), \"error\" (equivalent to passing --no-tests=error on the command line), or \"ignore\" (equivalent to passing --no-tests-ignore on the command line).",
- "enum": [
- "default", "error", "ignore"
- ]
- }
- }
- },
- "testPresetsOutputJUnitFile": {
- "type": "string",
- "description": "An optional string specifying a path to a JUnit file. Equivalent to passing --output-junit on the command line."
- },
- "testPresetsTestOutputTruncation": {
- "type": "string",
- "description": "An optional string specifying the test output truncation mode. Equivalent to passing --test-output-truncation on the command line. Must be one of the following values: \"tail\", \"middle\", or \"head\".",
- "enum": [
- "tail", "middle", "head"
- ]
- },
- "testPresetsOutputV10": {
- "type": "object",
- "description": "An optional object specifying output options.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsOutputObject" },
- {
- "properties": {
- "outputJUnitFile": { "$ref": "#/definitions/testPresetsOutputJUnitFile" },
- "testOutputTruncation": { "$ref": "#/definitions/testPresetsTestOutputTruncation" },
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsOutputV6": {
- "type": "object",
- "description": "An optional object specifying output options.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsOutputObject" },
- {
- "properties": {
- "outputJUnitFile": { "$ref": "#/definitions/testPresetsOutputJUnitFile" },
- "testOutputTruncation": { "$ref": "#/definitions/testPresetsTestOutputTruncation" }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsOutputV5": {
- "type": "object",
- "description": "An optional object specifying output options.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsOutputObject" },
- {
- "properties": {
- "testOutputTruncation": { "$ref": "#/definitions/testPresetsTestOutputTruncation" }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsOutputV2": {
- "type": "object",
- "description": "An optional object specifying output options.",
- "allOf": [
- { "$ref": "#/definitions/testPresetsOutputObject" }
- ],
- "unevaluatedProperties": false
- },
- "testPresetsOutputObject": {
- "properties": {
- "shortProgress": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --progress on the command line."
- },
- "verbosity": {
- "type": "string",
- "description": "An optional string specifying verbosity level. Valid values are \"default\" (equivalent to passing no verbosity flags on the command line), \"verbose\" (equivalent to passing --verbose on the command line), and \"extra\" (equivalent to passing --extra-verbose on the command line).",
- "enum": [
- "default", "verbose", "extra"
- ]
- },
- "debug": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --debug on the command line."
- },
- "outputOnFailure": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --output-on-failure on the command line."
- },
- "quiet": {
- "type": "boolean",
- "description": "An optional boolean. If true, equivalent to passing --quiet on the command line."
- },
- "outputLogFile": {
- "type": "string",
- "description": "An optional string specifying a path to a log file. Equivalent to passing --output-log on the command line."
- },
- "labelSummary": {
- "type": "boolean",
- "description": "An optional boolean. If false, equivalent to passing --no-label-summary on the command line."
- },
- "subprojectSummary": {
- "type": "boolean",
- "description": "An optional boolean. If false, equivalent to passing --no-subproject-summary on the command line."
- },
- "maxPassedTestOutputSize": {
- "type": "integer",
- "description": "An optional integer specifying the maximum output for passed tests in bytes. Equivalent to passing --test-output-size-passed on the command line."
- },
- "maxFailedTestOutputSize": {
- "type": "integer",
- "description": "An optional integer specifying the maximum output for failed tests in bytes. Equivalent to passing --test-output-size-failed on the command line."
- },
- "maxTestNameWidth": {
- "type": "integer",
- "description": "An optional integer specifying the maximum width of a test name to output. Equivalent to passing --max-width on the command line."
- }
- }
- },
- "testPresetsAdditionalPropertiesV11": {
- "properties": {
- "execution": { "$ref": "#/definitions/testPresetsExecutionV11" },
- "filter": {
- "type": "object",
- "description": "An optional object specifying how to filter the tests to run.",
- "properties": {
- "include": { "$ref": "#/definitions/testPresetsFilterIncludeV10" },
- "exclude": { "$ref": "#/definitions/testPresetsFilterExcludeV10" },
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- },
- "output": { "$ref": "#/definitions/testPresetsOutputV6" },
- "condition": { "$ref": "#/definitions/topConditionV10" }
- }
- },
- "testPresetsAdditionalPropertiesV10": {
- "properties": {
- "execution": { "$ref": "#/definitions/testPresetsExecutionV10" },
- "filter": {
- "type": "object",
- "description": "An optional object specifying how to filter the tests to run.",
- "properties": {
- "include": { "$ref": "#/definitions/testPresetsFilterIncludeV10" },
- "exclude": { "$ref": "#/definitions/testPresetsFilterExcludeV10" },
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- },
- "output": { "$ref": "#/definitions/testPresetsOutputV6" },
- "condition": { "$ref": "#/definitions/topConditionV10" }
- }
- },
- "testPresetsAdditionalPropertiesV6": {
- "properties": {
- "execution": { "$ref": "#/definitions/testPresetsExecutionV2" },
- "filter": {
- "type": "object",
- "description": "An optional object specifying how to filter the tests to run.",
- "properties": {
- "include": { "$ref": "#/definitions/testPresetsFilterIncludeV2" },
- "exclude": { "$ref": "#/definitions/testPresetsFilterExcludeV2" }
- }
- },
- "output": { "$ref": "#/definitions/testPresetsOutputV6" },
- "condition": { "$ref": "#/definitions/topConditionV3" }
- }
- },
- "testPresetsAdditionalPropertiesV5": {
- "properties": {
- "execution": { "$ref": "#/definitions/testPresetsExecutionV2" },
- "filter": {
- "type": "object",
- "description": "An optional object specifying how to filter the tests to run.",
- "properties": {
- "include": { "$ref": "#/definitions/testPresetsFilterIncludeV2" },
- "exclude": { "$ref": "#/definitions/testPresetsFilterExcludeV2" }
- }
- },
- "output": { "$ref": "#/definitions/testPresetsOutputV5" },
- "condition": { "$ref": "#/definitions/topConditionV3" }
- }
- },
- "testPresetsAdditionalPropertiesV3": {
- "allOf": [
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV2" },
- {
- "properties": {
- "condition": { "$ref": "#/definitions/topConditionV3" }
- }
- }
- ]
- },
- "testPresetsAdditionalPropertiesV2": {
- "properties": {
- "execution": { "$ref": "#/definitions/testPresetsExecutionV2" },
- "filter": {
- "type": "object",
- "description": "An optional object specifying how to filter the tests to run.",
- "properties": {
- "include": { "$ref": "#/definitions/testPresetsFilterIncludeV2" },
- "exclude": { "$ref": "#/definitions/testPresetsFilterExcludeV2" }
- }
- },
- "output": { "$ref": "#/definitions/testPresetsOutputV2" }
- }
- },
- "testPresetsItemsV2": {
- "allOf": [
- { "$ref": "#/definitions/commonPropertiesAll" },
- { "$ref": "#/definitions/configureBuildTestPackagePresetsEnvironmentProperty" },
- {
- "properties": {
- "hidden": {
- "type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
- },
- "inherits": {
- "anyOf": [
- {
- "type": "string",
- "description": "An optional string representing the name of the test preset to inherit from.",
- "minLength": 1
- },
- {
- "type": "array",
- "description": "An optional array of strings representing the names of test presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
- "items": {
- "type": "string",
- "description": "An optional string representing the name of the preset to inherit from.",
- "minLength": 1
- }
- }
- ]
- },
- "configurePreset": {
- "type": "string",
- "description": "An optional string specifying the name of a configure preset to associate with this test preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.",
- "minLength": 1
- },
- "inheritConfigureEnvironment": {
- "type": "boolean",
- "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited test preset environments, but before environment variables explicitly specified in this test preset."
- },
- "configuration": {
- "type": "string",
- "description": "An optional string. Equivalent to passing --build-config on the command line."
- },
- "overwriteConfigurationFile": {
- "type": "array",
- "description": "An optional array of configuration options to overwrite options specified in the CTest configuration file. Equivalent to passing ``--overwrite`` for each value in the array.",
- "items": {
- "type": "string",
- "description": "An option written as a key-value pair in the form \"key=value\"."
- }
- }
- }
- }
- ],
- "required": [
- "name"
- ]
- },
- "testPresetsV11": {
- "type": "array",
- "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 11 and higher.",
- "items": {
- "type": "object",
- "description": "A test preset object",
- "allOf": [
- { "$ref": "#/definitions/testPresetsItemsV2" },
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV11" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- },
- "testPresetsV10": {
- "type": "array",
- "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 10 and higher.",
- "items": {
- "type": "object",
- "description": "A test preset object",
- "allOf": [
- { "$ref": "#/definitions/testPresetsItemsV2" },
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV10" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- },
- "testPresetsV6": {
- "type": "array",
- "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 6 and higher.",
- "items": {
- "type": "object",
- "description": "A test preset object",
- "allOf": [
- { "$ref": "#/definitions/testPresetsItemsV2" },
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV6" }
- ],
- "unevaluatedProperties": false
- }
- },
- "testPresetsV5": {
- "type": "array",
- "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 5 and higher.",
- "items": {
- "type": "object",
- "description": "A test preset object",
- "allOf": [
- { "$ref": "#/definitions/testPresetsItemsV2" },
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV5" }
- ],
- "unevaluatedProperties": false
- }
- },
- "testPresetsV3": {
- "type": "array",
- "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 3 and higher.",
- "items": {
- "type": "object",
- "description": "A test preset object",
- "allOf": [
- { "$ref": "#/definitions/testPresetsItemsV2" },
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV3" }
- ],
- "unevaluatedProperties": false
- }
- },
- "testPresetsV2": {
- "type": "array",
- "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.",
- "items": {
- "type": "object",
- "description": "A test preset object",
- "allOf": [
- { "$ref": "#/definitions/testPresetsItemsV2" },
- { "$ref": "#/definitions/testPresetsAdditionalPropertiesV2" }
- ],
- "unevaluatedProperties": false
- }
- },
- "packagePresetsOutputV10": {
- "type": "object",
- "description": "An optional object specifying output options.",
- "allOf": [
- { "$ref": "#/definitions/packagePresetsOutputObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- "packagePresetsOutputV6": {
- "type": "object",
- "description": "An optional object specifying output options.",
- "allOf": [
- { "$ref": "#/definitions/packagePresetsOutputObject" }
- ],
- "unevaluatedProperties": false
- },
- "packagePresetsOutputObject": {
- "properties": {
- "debug": {
- "type": "boolean",
- "description": "An optional boolean specifying whether or not to print debug information. A value of true is equivalent to passing --debug on the command line."
- },
- "verbose": {
- "type": "boolean",
- "description": "An optional boolean specifying whether or not to print verbosely. A value of true is equivalent to passing --verbose on the command line."
- }
- }
- },
- "packagePresetsAdditionalPropertiesV10": {
- "properties": {
- "output": { "$ref": "#/definitions/packagePresetsOutputV10" },
- "condition": { "$ref": "#/definitions/topConditionV10" },
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- },
- "packagePresetsAdditionalPropertiesV6": {
- "properties": {
- "output": { "$ref": "#/definitions/packagePresetsOutputV6" },
- "condition": { "$ref": "#/definitions/topConditionV3" }
- }
- },
- "packagePresetsItemsV6": {
- "allOf": [
- { "$ref": "#/definitions/commonPropertiesAll" },
- { "$ref": "#/definitions/configureBuildTestPackagePresetsEnvironmentProperty" },
- {
- "properties": {
- "hidden": {
- "type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
- },
- "inherits": {
- "anyOf": [
- {
- "type": "string",
- "description": "An optional string representing the name of the package preset to inherit from.",
- "minLength": 1
- },
- {
- "type": "array",
- "description": "An optional array of strings representing the names of package presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
- "items": {
- "type": "string",
- "description": "An optional string representing the name of the preset to inherit from.",
- "minLength": 1
- }
- }
- ]
- },
- "configurePreset": {
- "type": "string",
- "description": "An optional string specifying the name of a configure preset to associate with this package preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.",
- "minLength": 1
- },
- "inheritConfigureEnvironment": {
- "type": "boolean",
- "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited package preset environments, but before environment variables explicitly specified in this package preset."
- },
- "generators": {
- "type": "array",
- "description": "An optional list of strings representing generators for CPack to use.",
- "items": {
- "type": "string",
- "description": "An optional string representing the name of the CPack generator to use."
- }
- },
- "configurations": {
- "type": "array",
- "description": "An optional list of strings representing build configurations for CPack to package.",
- "items": {
- "type": "string",
- "description": "An optional string representing the name of the configuration to use."
- }
- },
- "variables": {
- "type": "object",
- "description": "An optional map of variables to pass to CPack, equivalent to -D arguments. Each key is the name of a variable, and the value is the string to assign to that variable.",
- "items": {
- "type": "string",
- "description": "An optional string representing the value of the variable."
- }
- },
- "configFile": {
- "type": "string",
- "description": "An optional string representing the config file for CPack to use."
- },
- "packageName": {
- "type": "string",
- "description": "An optional string representing the package name."
- },
- "packageVersion": {
- "type": "string",
- "description": "An optional string representing the package version."
- },
- "packageDirectory": {
- "type": "string",
- "description": "An optional string representing the directory in which to place the package."
- },
- "vendorName": {
- "type": "string",
- "description": "An optional string representing the vendor name."
- }
- }
- }
- ],
- "required": [
- "name"
- ]
- },
- "packagePresetsV10": {
- "type": "array",
- "description": "An optional array of package preset objects. Used to specify arguments to cpack. Available in version 10 and higher.",
- "items": {
- "type": "object",
- "description": "An optional package preset object.",
- "allOf": [
- { "$ref": "#/definitions/packagePresetsItemsV6" },
- { "$ref": "#/definitions/packagePresetsAdditionalPropertiesV10" }
- ],
- "unevaluatedProperties": false
- }
- },
- "packagePresetsV6": {
- "type": "array",
- "description": "An optional array of package preset objects. Used to specify arguments to cpack. Available in version 6 and higher.",
- "items": {
- "type": "object",
- "description": "An optional package preset object.",
- "allOf": [
- { "$ref": "#/definitions/packagePresetsItemsV6" },
- { "$ref": "#/definitions/packagePresetsAdditionalPropertiesV6" }
- ],
- "unevaluatedProperties": false
- }
- },
- "workflowPresetsStepsV10": {
- "type": "array",
- "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.",
- "items": {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/workflowPresetsStepsObject" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- }
- },
- "workflowPresetsStepsV6": {
- "type": "array",
- "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.",
- "items": {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/workflowPresetsStepsObject" }
- ],
- "unevaluatedProperties": false
- }
- },
- "workflowPresetsStepsObject": {
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string. The first step must be configure. Subsequent steps must be either build, test, or package.",
- "enum": ["configure", "build", "test", "package"]
- },
- "name": {
- "type": "string",
- "description": "A required string representing the name of the configure, build, test, or package preset to run as this workflow step.",
- "minLength": 1
- }
- },
- "required": [
- "type",
- "name"
- ]
- },
- "workflowPresetsAdditionalPropertiesV10": {
- "properties": {
- "steps": { "$ref": "#/definitions/workflowPresetsStepsV10" },
- "$comment": { "$ref": "#/definitions/$comment" }
- }
- },
- "workflowPresetsAdditionalPropertiesV6": {
- "properties": {
- "steps": { "$ref": "#/definitions/workflowPresetsStepsV6" }
- }
- },
- "workflowPresetsV10": {
- "type": "array",
- "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 10 and higher.",
- "items": {
- "type": "object",
- "description": "An optional workflow preset object",
- "allOf": [
- { "$ref": "#/definitions/commonPropertiesAll" },
- { "$ref": "#/definitions/workflowPresetsAdditionalPropertiesV10" }
- ],
- "required": [
- "name",
- "steps"
- ],
- "unevaluatedProperties": false
- }
- },
- "workflowPresetsV6": {
- "type": "array",
- "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.",
- "items": {
- "type": "object",
- "description": "An optional workflow preset object",
- "allOf": [
- { "$ref": "#/definitions/commonPropertiesAll" },
- { "$ref": "#/definitions/workflowPresetsAdditionalPropertiesV6" }
- ],
- "required": [
- "name",
- "steps"
- ],
- "unevaluatedProperties": false
- }
- },
- "conditionAsBooleanV3": {
- "type": "boolean",
- "description": "A boolean which provides a constant value for the condition's evaluation."
- },
- "conditionAsObjectConstV3": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string specifying the type of the condition.",
- "const": "const"
- },
- "value": {
- "type": "boolean",
- "description": "A required boolean which provides a constant value for the condition's evaluation."
- }
- },
- "required": [
- "type",
- "value"
- ]
- },
- "conditionAsObjectEqualsV3": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string specifying the type of the condition.",
- "enum": [ "equals", "notEquals" ]
- },
- "lhs": {
- "type": "string",
- "description": "First string to compare. This field supports macro expansion."
- },
- "rhs": {
- "type": "string",
- "description": "Second string to compare. This field supports macro expansion."
- }
- },
- "required": [
- "type",
- "lhs",
- "rhs"
- ]
- },
- "conditionAsObjectInListV3": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string specifying the type of the condition.",
- "enum": [ "inList", "notInList" ]
- },
- "string": {
- "type": "string",
- "description": "A required string to search for. This field supports macro expansion."
- },
- "list": {
- "type": "array",
- "description": "A required list of strings to search. This field supports macro expansion, and uses short-circuit evaluation.",
- "items": {
- "type": "string"
- }
- }
- },
- "required": [
- "type",
- "string",
- "list"
- ]
- },
- "conditionAsObjectMatchesV3": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string specifying the type of the condition.",
- "enum": [ "matches", "notMatches" ]
- },
- "string": {
- "type": "string",
- "description": "A required string to search. This field supports macro expansion."
- },
- "regex": {
- "type": "string",
- "description": "A required regular expression to search for. This field supports macro expansion."
- }
- },
- "required": [
- "type",
- "string",
- "regex"
- ]
- },
- "conditionAsObjectAggregationV3": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string specifying the type of the condition.",
- "enum": [ "anyOf", "allOf" ]
- },
- "conditions": {
- "type": "array",
- "description": "A required array of condition objects. These conditions use short-circuit evaluation.",
- "items": {
- "properties": {
- "condition": { "$ref": "#/definitions/conditionV3" }
- }
- }
- }
- },
- "required": [
- "type",
- "conditions"
- ]
- },
- "conditionAsObjectNotV3": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "description": "A required string specifying the type of the condition.",
- "const": "not"
- },
- "condition": { "$ref": "#/definitions/conditionV3" }
- },
- "required": [
- "type",
- "condition"
- ]
- },
- "conditionV10": {
- "anyOf": [
- { "$ref": "#/definitions/conditionAsBooleanV3" },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectConstV3" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectEqualsV3" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectInListV3" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectMatchesV3" },
- { "$ref": "#/definitions/commentAsProperty" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectAggregationV3" },
- { "$ref": "#/definitions/commentAsProperty" },
- {
- "properties": {
- "conditions": {
- "type": "array",
- "items": { "$ref": "#/definitions/conditionV10" }
- }
- }
- }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectNotV3" },
- { "$ref": "#/definitions/commentAsProperty" },
- {
- "properties": {
- "condition": { "$ref": "#/definitions/conditionV10" }
- }
- }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "conditionV3": {
- "anyOf": [
- { "$ref": "#/definitions/conditionAsBooleanV3" },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectConstV3" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectEqualsV3" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectInListV3" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectMatchesV3" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectAggregationV3" }
- ],
- "unevaluatedProperties": false
- },
- {
- "type": "object",
- "allOf": [
- { "$ref": "#/definitions/conditionAsObjectNotV3" }
- ],
- "unevaluatedProperties": false
- }
- ]
- },
- "topConditionAsNullV3": {
- "type": "null",
- "description": "Null indicates that the condition always evaluates to true and is not inherited."
- },
- "topConditionV10": {
- "anyOf": [
- { "$ref": "#/definitions/conditionV10" },
- { "$ref": "#/definitions/topConditionAsNullV3" }
- ]
- },
- "topConditionV3": {
- "anyOf": [
- { "$ref": "#/definitions/conditionV3" },
- { "$ref": "#/definitions/topConditionAsNullV3" }
- ]
- },
- "include": {
+ "include@v4..": {
"type": "array",
"description": "An optional array of strings representing files to include. If the filenames are not absolute, they are considered relative to the current file.",
"items": {
"type": "string"
}
+ },
+ "vendor@v1..": {
+ "type": "object",
+ "description": "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, the keys should be a vendor-specific domain name followed by a /-separated path. For example, the Example IDE 1.0 could use example.com/ExampleIDE/1.0. The value of each field can be anything desired by the vendor, though will typically be a map.",
+ "properties": {}
+ },
+ "configurePresets@v1..v2": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A configure preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/configurePresets.name@v1.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/configurePresets.hidden@v1.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/configurePresets.inherits@v1.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/configurePresets.vendor@v1.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/configurePresets.displayName@v1.."
+ },
+ "description": {
+ "$ref": "#/definitions/configurePresets.description@v1.."
+ },
+ "generator": {
+ "$ref": "#/definitions/configurePresets.generator@v1..v2"
+ },
+ "architecture": {
+ "$ref": "#/definitions/configurePresets.architecture@v1..v9"
+ },
+ "toolset": {
+ "$ref": "#/definitions/configurePresets.toolset@v1..v9"
+ },
+ "binaryDir": {
+ "$ref": "#/definitions/configurePresets.binaryDir@v1..v2"
+ },
+ "cmakeExecutable": {
+ "$ref": "#/definitions/configurePresets.cmakeExecutable@v1.."
+ },
+ "cacheVariables": {
+ "$ref": "#/definitions/configurePresets.cacheVariables@v1..v9"
+ },
+ "environment": {
+ "$ref": "#/definitions/configurePresets.environment@v1.."
+ },
+ "warnings": {
+ "$ref": "#/definitions/configurePresets.warnings@v1..v9"
+ },
+ "errors": {
+ "$ref": "#/definitions/configurePresets.errors@v1..v9"
+ },
+ "debug": {
+ "$ref": "#/definitions/configurePresets.debug@v1..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "configurePresets@v3..v6": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A configure preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/configurePresets.name@v1.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/configurePresets.hidden@v1.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/configurePresets.inherits@v1.."
+ },
+ "condition": {
+ "$ref": "#/definitions/configurePresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/configurePresets.vendor@v1.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/configurePresets.displayName@v1.."
+ },
+ "description": {
+ "$ref": "#/definitions/configurePresets.description@v1.."
+ },
+ "generator": {
+ "$ref": "#/definitions/configurePresets.generator@v3.."
+ },
+ "architecture": {
+ "$ref": "#/definitions/configurePresets.architecture@v1..v9"
+ },
+ "toolset": {
+ "$ref": "#/definitions/configurePresets.toolset@v1..v9"
+ },
+ "toolchainFile": {
+ "$ref": "#/definitions/configurePresets.toolchainFile@v3.."
+ },
+ "binaryDir": {
+ "$ref": "#/definitions/configurePresets.binaryDir@v3.."
+ },
+ "installDir": {
+ "$ref": "#/definitions/configurePresets.installDir@v3.."
+ },
+ "cmakeExecutable": {
+ "$ref": "#/definitions/configurePresets.cmakeExecutable@v1.."
+ },
+ "cacheVariables": {
+ "$ref": "#/definitions/configurePresets.cacheVariables@v1..v9"
+ },
+ "environment": {
+ "$ref": "#/definitions/configurePresets.environment@v1.."
+ },
+ "warnings": {
+ "$ref": "#/definitions/configurePresets.warnings@v1..v9"
+ },
+ "errors": {
+ "$ref": "#/definitions/configurePresets.errors@v1..v9"
+ },
+ "debug": {
+ "$ref": "#/definitions/configurePresets.debug@v1..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "configurePresets@v7..v9": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A configure preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/configurePresets.name@v1.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/configurePresets.hidden@v1.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/configurePresets.inherits@v1.."
+ },
+ "condition": {
+ "$ref": "#/definitions/configurePresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/configurePresets.vendor@v1.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/configurePresets.displayName@v1.."
+ },
+ "description": {
+ "$ref": "#/definitions/configurePresets.description@v1.."
+ },
+ "generator": {
+ "$ref": "#/definitions/configurePresets.generator@v3.."
+ },
+ "architecture": {
+ "$ref": "#/definitions/configurePresets.architecture@v1..v9"
+ },
+ "toolset": {
+ "$ref": "#/definitions/configurePresets.toolset@v1..v9"
+ },
+ "toolchainFile": {
+ "$ref": "#/definitions/configurePresets.toolchainFile@v3.."
+ },
+ "binaryDir": {
+ "$ref": "#/definitions/configurePresets.binaryDir@v3.."
+ },
+ "installDir": {
+ "$ref": "#/definitions/configurePresets.installDir@v3.."
+ },
+ "cmakeExecutable": {
+ "$ref": "#/definitions/configurePresets.cmakeExecutable@v1.."
+ },
+ "cacheVariables": {
+ "$ref": "#/definitions/configurePresets.cacheVariables@v1..v9"
+ },
+ "environment": {
+ "$ref": "#/definitions/configurePresets.environment@v1.."
+ },
+ "warnings": {
+ "$ref": "#/definitions/configurePresets.warnings@v1..v9"
+ },
+ "errors": {
+ "$ref": "#/definitions/configurePresets.errors@v1..v9"
+ },
+ "debug": {
+ "$ref": "#/definitions/configurePresets.debug@v1..v9"
+ },
+ "trace": {
+ "$ref": "#/definitions/configurePresets.trace@v7..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "configurePresets@v10..v11": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A configure preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/configurePresets.name@v1.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/configurePresets.hidden@v1.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/configurePresets.inherits@v1.."
+ },
+ "condition": {
+ "$ref": "#/definitions/configurePresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/configurePresets.vendor@v1.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/configurePresets.displayName@v1.."
+ },
+ "description": {
+ "$ref": "#/definitions/configurePresets.description@v1.."
+ },
+ "generator": {
+ "$ref": "#/definitions/configurePresets.generator@v3.."
+ },
+ "architecture": {
+ "$ref": "#/definitions/configurePresets.architecture@v10.."
+ },
+ "toolset": {
+ "$ref": "#/definitions/configurePresets.toolset@v10.."
+ },
+ "toolchainFile": {
+ "$ref": "#/definitions/configurePresets.toolchainFile@v3.."
+ },
+ "graphviz": {
+ "$ref": "#/definitions/configurePresets.graphviz@v10.."
+ },
+ "binaryDir": {
+ "$ref": "#/definitions/configurePresets.binaryDir@v3.."
+ },
+ "installDir": {
+ "$ref": "#/definitions/configurePresets.installDir@v3.."
+ },
+ "cmakeExecutable": {
+ "$ref": "#/definitions/configurePresets.cmakeExecutable@v1.."
+ },
+ "cacheVariables": {
+ "$ref": "#/definitions/configurePresets.cacheVariables@v10.."
+ },
+ "environment": {
+ "$ref": "#/definitions/configurePresets.environment@v1.."
+ },
+ "warnings": {
+ "$ref": "#/definitions/configurePresets.warnings@v10..v11"
+ },
+ "errors": {
+ "$ref": "#/definitions/configurePresets.errors@v10..v11"
+ },
+ "debug": {
+ "$ref": "#/definitions/configurePresets.debug@v10.."
+ },
+ "trace": {
+ "$ref": "#/definitions/configurePresets.trace@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "configurePresets@v12": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A configure preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/configurePresets.name@v1.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/configurePresets.hidden@v1.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/configurePresets.inherits@v1.."
+ },
+ "condition": {
+ "$ref": "#/definitions/configurePresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/configurePresets.vendor@v1.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/configurePresets.displayName@v1.."
+ },
+ "description": {
+ "$ref": "#/definitions/configurePresets.description@v1.."
+ },
+ "generator": {
+ "$ref": "#/definitions/configurePresets.generator@v3.."
+ },
+ "architecture": {
+ "$ref": "#/definitions/configurePresets.architecture@v10.."
+ },
+ "toolset": {
+ "$ref": "#/definitions/configurePresets.toolset@v10.."
+ },
+ "toolchainFile": {
+ "$ref": "#/definitions/configurePresets.toolchainFile@v3.."
+ },
+ "graphviz": {
+ "$ref": "#/definitions/configurePresets.graphviz@v10.."
+ },
+ "binaryDir": {
+ "$ref": "#/definitions/configurePresets.binaryDir@v3.."
+ },
+ "installDir": {
+ "$ref": "#/definitions/configurePresets.installDir@v3.."
+ },
+ "cmakeExecutable": {
+ "$ref": "#/definitions/configurePresets.cmakeExecutable@v1.."
+ },
+ "cacheVariables": {
+ "$ref": "#/definitions/configurePresets.cacheVariables@v10.."
+ },
+ "environment": {
+ "$ref": "#/definitions/configurePresets.environment@v1.."
+ },
+ "warnings": {
+ "$ref": "#/definitions/configurePresets.warnings@v12"
+ },
+ "errors": {
+ "$ref": "#/definitions/configurePresets.errors@v12"
+ },
+ "debug": {
+ "$ref": "#/definitions/configurePresets.debug@v10.."
+ },
+ "trace": {
+ "$ref": "#/definitions/configurePresets.trace@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "configurePresets.name@v1..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the cmake --preset option. There must not be two configure presets in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name. However, a configure preset may have the same name as a build, test, package, or workflow preset."
+ },
+ "configurePresets.hidden@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset= argument, will not show up in the CMake GUI, and does not have to have a valid generator or binaryDir, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "configurePresets.inherits@v1..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of presets from which to inherit. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ }
+ }
+ ]
+ },
+ "configurePresets.condition@v3..v9": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v3..v9"
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "configurePresets.condition@v10..": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v10.."
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "configurePresets.vendor@v1..": {
+ "type": "object",
+ "minLength": 1,
+ "description": "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.",
+ "properties": {}
+ },
+ "configurePresets.displayName@v1..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "configurePresets.description@v1..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "configurePresets.generator@v1..v2": {
+ "type": "string",
+ "description": "An optional string representing the generator to use for the preset. If generator is not specified, it must be inherited from the inherits preset (unless this preset is hidden). Note that for Visual Studio generators, unlike in the command line -G argument, you cannot include the platform name in the generator name. Use the architecture field instead."
+ },
+ "configurePresets.generator@v3..": {
+ "type": "string",
+ "description": "An optional string representing the generator to use for the preset. If generator is not specified, the normal generator discovery procedure is used. Note that for Visual Studio generators, unlike in the command line -G argument, you cannot include the platform name in the generator name. Use the architecture field instead."
+ },
+ "configurePresets.architecture@v1..v9": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the platform for generators that support it."
+ },
+ {
+ "type": "object",
+ "description": "An optional string representing the platform for generators that support it.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "value": {
+ "$ref": "#/definitions/configurePresets.architecture.value@v1.."
+ },
+ "strategy": {
+ "$ref": "#/definitions/configurePresets.architecture.strategy@v1.."
+ }
+ }
+ }
+ ]
+ },
+ "configurePresets.architecture@v10..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the platform for generators that support it."
+ },
+ {
+ "type": "object",
+ "description": "An optional string representing the platform for generators that support it.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "value": {
+ "$ref": "#/definitions/configurePresets.architecture.value@v1.."
+ },
+ "strategy": {
+ "$ref": "#/definitions/configurePresets.architecture.strategy@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ }
+ ]
+ },
+ "configurePresets.architecture.value@v1..": {
+ "type": "string",
+ "description": "An optional string representing the value."
+ },
+ "configurePresets.architecture.strategy@v1..": {
+ "type": "string",
+ "enum": [
+ "set",
+ "external"
+ ],
+ "description": "An optional string telling CMake how to handle the field. Valid values are: \"set\" Set the respective value. This will result in an error for generators that do not support the respective field. \"external\" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake."
+ },
+ "configurePresets.toolset@v1..v9": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the toolset for generators that support it."
+ },
+ {
+ "type": "object",
+ "description": "An optional string representing the toolset for generators that support it.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "value": {
+ "$ref": "#/definitions/configurePresets.toolset.value@v1.."
+ },
+ "strategy": {
+ "$ref": "#/definitions/configurePresets.toolset.strategy@v1.."
+ }
+ }
+ }
+ ]
+ },
+ "configurePresets.toolset@v10..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the toolset for generators that support it."
+ },
+ {
+ "type": "object",
+ "description": "An optional string representing the toolset for generators that support it.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "value": {
+ "$ref": "#/definitions/configurePresets.toolset.value@v1.."
+ },
+ "strategy": {
+ "$ref": "#/definitions/configurePresets.toolset.strategy@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ }
+ ]
+ },
+ "configurePresets.toolset.value@v1..": {
+ "type": "string",
+ "description": "An optional string representing the value."
+ },
+ "configurePresets.toolset.strategy@v1..": {
+ "type": "string",
+ "enum": [
+ "set",
+ "external"
+ ],
+ "description": "An optional string telling CMake how to handle the field. Valid values are: \"set\" Set the respective value. This will result in an error for generators that do not support the respective field. \"external\" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake."
+ },
+ "configurePresets.toolchainFile@v3..": {
+ "type": "string",
+ "description": "An optional string representing the path to the toolchain file. This field supports macro expansion. If a relative path is specified, it is calculated relative to the build directory, and if not found, relative to the source directory."
+ },
+ "configurePresets.graphviz@v10..": {
+ "type": "string",
+ "description": "An optional string specifying the path to the graphviz dot file."
+ },
+ "configurePresets.binaryDir@v1..v2": {
+ "type": "string",
+ "description": "An optional string representing the path to the output binary directory. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory. If binaryDir is not specified, it must be inherited from the inherits preset (unless this preset is hidden)."
+ },
+ "configurePresets.binaryDir@v3..": {
+ "type": "string",
+ "description": "An optional string representing the path to the output binary directory. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory. If binaryDir is not specified, the path is calculated using regular methods."
+ },
+ "configurePresets.installDir@v3..": {
+ "type": "string",
+ "description": "An optional string representing the path to the installation directory, which will be used as the CMAKE_INSTALL_PREFIX variable. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory."
+ },
+ "configurePresets.cmakeExecutable@v1..": {
+ "type": "string",
+ "description": "An optional string representing the path to the CMake executable to use for this preset. This is reserved for use by IDEs, and is not used by CMake itself. IDEs that use this field should expand any macros in it."
+ },
+ "configurePresets.cacheVariables@v1..v9": {
+ "type": "object",
+ "description": "An optional map of cache variables. The key is the variable name (which must not be an empty string). Cache variables are inherited through the inherits field, and the preset's variables will be the union of its own cacheVariables and the cacheVariables from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied.",
+ "propertyNames": {
+ "pattern": "^.+$"
+ },
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "boolean",
+ "description": "A boolean representing the value of the variable. Equivalent to \"TRUE\" or \"FALSE\""
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable (which supports macro expansion)."
+ },
+ {
+ "type": "object",
+ "description": "An optional object representing the cache variables for generators that support it.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/configurePresets.cacheVariables.type@v1.."
+ },
+ "value": {
+ "$ref": "#/definitions/configurePresets.cacheVariables.value@v1.."
+ }
+ },
+ "required": [
+ "value"
+ ]
+ }
+ ]
+ }
+ },
+ "configurePresets.cacheVariables@v10..": {
+ "type": "object",
+ "description": "An optional map of cache variables. The key is the variable name (which must not be an empty string). Cache variables are inherited through the inherits field, and the preset's variables will be the union of its own cacheVariables and the cacheVariables from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied.",
+ "propertyNames": {
+ "pattern": "^.+$"
+ },
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "boolean",
+ "description": "A boolean representing the value of the variable. Equivalent to \"TRUE\" or \"FALSE\""
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable (which supports macro expansion)."
+ },
+ {
+ "type": "object",
+ "description": "An optional object representing the cache variables for generators that support it.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/configurePresets.cacheVariables.type@v1.."
+ },
+ "value": {
+ "$ref": "#/definitions/configurePresets.cacheVariables.value@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "value"
+ ]
+ }
+ ]
+ }
+ },
+ "configurePresets.cacheVariables.type@v1..": {
+ "type": "string",
+ "enum": [
+ "BOOL",
+ "FILEPATH",
+ "PATH",
+ "STRING",
+ "INTERNAL"
+ ],
+ "description": "An optional string representing the type of the variable. It should be BOOL, FILEPATH, PATH, STRING, or INTERNAL."
+ },
+ "configurePresets.cacheVariables.value@v1..": {
+ "anyOf": [
+ {
+ "type": "boolean",
+ "description": "A boolean representing the value of the variable. Equivalent to \"TRUE\" or \"FALSE\"."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable (which supports macro expansion)."
+ }
+ ]
+ },
+ "configurePresets.environment@v1..": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "propertyNames": {
+ "pattern": "^.+$"
+ },
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ }
+ },
+ "configurePresets.warnings@v1..v9": {
+ "type": "object",
+ "description": "An optional object specifying the warnings to enable.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "deprecated": {
+ "$ref": "#/definitions/configurePresets.warnings.deprecated@v1.."
+ },
+ "dev": {
+ "$ref": "#/definitions/configurePresets.warnings.dev@v1..v11"
+ },
+ "uninitialized": {
+ "$ref": "#/definitions/configurePresets.warnings.uninitialized@v1.."
+ },
+ "unusedCli": {
+ "$ref": "#/definitions/configurePresets.warnings.unusedCli@v1.."
+ },
+ "systemVars": {
+ "$ref": "#/definitions/configurePresets.warnings.systemVars@v1.."
+ }
+ }
+ },
+ "configurePresets.warnings@v10..v11": {
+ "type": "object",
+ "description": "An optional object specifying the warnings to enable.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "deprecated": {
+ "$ref": "#/definitions/configurePresets.warnings.deprecated@v1.."
+ },
+ "dev": {
+ "$ref": "#/definitions/configurePresets.warnings.dev@v1..v11"
+ },
+ "uninitialized": {
+ "$ref": "#/definitions/configurePresets.warnings.uninitialized@v1.."
+ },
+ "unusedCli": {
+ "$ref": "#/definitions/configurePresets.warnings.unusedCli@v1.."
+ },
+ "systemVars": {
+ "$ref": "#/definitions/configurePresets.warnings.systemVars@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "configurePresets.warnings@v12": {
+ "type": "object",
+ "description": "An optional object specifying the warnings to enable.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/configurePresets.warnings.author@v12"
+ },
+ "deprecated": {
+ "$ref": "#/definitions/configurePresets.warnings.deprecated@v1.."
+ },
+ "uninitialized": {
+ "$ref": "#/definitions/configurePresets.warnings.uninitialized@v1.."
+ },
+ "unusedCli": {
+ "$ref": "#/definitions/configurePresets.warnings.unusedCli@v1.."
+ },
+ "systemVars": {
+ "$ref": "#/definitions/configurePresets.warnings.systemVars@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "configurePresets.warnings.author@v12": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Wauthor or -Wno-author on the command line. This may not be set to false if errors.author is set to true."
+ },
+ "configurePresets.warnings.deprecated@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Wdeprecated or -Wno-deprecated on the command line. This may not be set to false if errors.deprecated is set to true."
+ },
+ "configurePresets.warnings.dev@v1..v11": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Wdev or -Wno-dev on the command line. This may not be set to false if errors.dev is set to true."
+ },
+ "configurePresets.warnings.uninitialized@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Wuninitialized or -Wno-uninitialized on the command line. This may not be set to false if errors.uninitialized is set to true."
+ },
+ "configurePresets.warnings.unusedCli@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Wunused-cli or -Wno-unused-cli on the command line. This may not be set to false if errors.unusedCli is set to true."
+ },
+ "configurePresets.warnings.systemVars@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Setting this to true is equivalent to passing --check-system-vars on the command line."
+ },
+ "configurePresets.errors@v1..v9": {
+ "type": "object",
+ "description": "An optional object specifying the errors to enable.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "deprecated": {
+ "$ref": "#/definitions/configurePresets.errors.deprecated@v1.."
+ },
+ "dev": {
+ "$ref": "#/definitions/configurePresets.errors.dev@v1..v11"
+ }
+ }
+ },
+ "configurePresets.errors@v10..v11": {
+ "type": "object",
+ "description": "An optional object specifying the errors to enable.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "deprecated": {
+ "$ref": "#/definitions/configurePresets.errors.deprecated@v1.."
+ },
+ "dev": {
+ "$ref": "#/definitions/configurePresets.errors.dev@v1..v11"
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "configurePresets.errors@v12": {
+ "type": "object",
+ "description": "An optional object specifying the errors to enable.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/configurePresets.errors.author@v12"
+ },
+ "deprecated": {
+ "$ref": "#/definitions/configurePresets.errors.deprecated@v1.."
+ },
+ "uninitialized": {
+ "$ref": "#/definitions/configurePresets.errors.uninitialized@v12"
+ },
+ "unusedCli": {
+ "$ref": "#/definitions/configurePresets.errors.unusedCli@v12"
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "configurePresets.errors.author@v12": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Werror=author or -Wno-error=author on the command line. This may not be set to true if warnings.author is set to false."
+ },
+ "configurePresets.errors.deprecated@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Werror=deprecated or -Wno-error=deprecated on the command line. This may not be set to true if warnings.deprecated is set to false."
+ },
+ "configurePresets.errors.dev@v1..v11": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Werror=dev or -Wno-error=dev on the command line. This may not be set to true if warnings.dev is set to false."
+ },
+ "configurePresets.errors.uninitialized@v12": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Werror=uninitialized or -Wno-error=uninitialized on the command line. This may not be set to true if warnings.uninitialized is set to false."
+ },
+ "configurePresets.errors.unusedCli@v12": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing -Werror=unused-cli or -Wno-error=unused-cli on the command line. This may not be set to true if warnings.unusedCli is set to false."
+ },
+ "configurePresets.debug@v1..v9": {
+ "type": "object",
+ "description": "An optional object specifying debug options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "output": {
+ "$ref": "#/definitions/configurePresets.debug.output@v1.."
+ },
+ "tryCompile": {
+ "$ref": "#/definitions/configurePresets.debug.tryCompile@v1.."
+ },
+ "find": {
+ "$ref": "#/definitions/configurePresets.debug.find@v1.."
+ }
+ }
+ },
+ "configurePresets.debug@v10..": {
+ "type": "object",
+ "description": "An optional object specifying debug options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "output": {
+ "$ref": "#/definitions/configurePresets.debug.output@v1.."
+ },
+ "tryCompile": {
+ "$ref": "#/definitions/configurePresets.debug.tryCompile@v1.."
+ },
+ "find": {
+ "$ref": "#/definitions/configurePresets.debug.find@v1.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "configurePresets.debug.output@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Setting this to true is equivalent to passing --debug-output on the command line."
+ },
+ "configurePresets.debug.tryCompile@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Setting this to true is equivalent to passing --debug-trycompile on the command line."
+ },
+ "configurePresets.debug.find@v1..": {
+ "type": "boolean",
+ "description": "An optional boolean. Setting this to true is equivalent to passing --debug-find on the command line."
+ },
+ "configurePresets.trace@v7..v9": {
+ "type": "object",
+ "description": "An optional object specifying trace options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "mode": {
+ "$ref": "#/definitions/configurePresets.trace.mode@v7.."
+ },
+ "format": {
+ "$ref": "#/definitions/configurePresets.trace.format@v7.."
+ },
+ "source": {
+ "$ref": "#/definitions/configurePresets.trace.source@v7.."
+ },
+ "redirect": {
+ "$ref": "#/definitions/configurePresets.trace.redirect@v7.."
+ }
+ }
+ },
+ "configurePresets.trace@v10..": {
+ "type": "object",
+ "description": "An optional object specifying trace options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "mode": {
+ "$ref": "#/definitions/configurePresets.trace.mode@v7.."
+ },
+ "format": {
+ "$ref": "#/definitions/configurePresets.trace.format@v7.."
+ },
+ "source": {
+ "$ref": "#/definitions/configurePresets.trace.source@v7.."
+ },
+ "redirect": {
+ "$ref": "#/definitions/configurePresets.trace.redirect@v7.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "configurePresets.trace.mode@v7..": {
+ "type": "string",
+ "enum": [
+ "on",
+ "off",
+ "expand"
+ ],
+ "description": "An optional string that specifies the trace mode."
+ },
+ "configurePresets.trace.format@v7..": {
+ "type": "string",
+ "enum": [
+ "human",
+ "json-v1"
+ ],
+ "description": "An optional string that specifies the trace output format."
+ },
+ "configurePresets.trace.source@v7..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the path to one source file to be traced."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the paths to source files to be traced.",
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A string representing the path to one source file to be traced."
+ }
+ }
+ ]
+ },
+ "configurePresets.trace.redirect@v7..": {
+ "type": "string",
+ "description": "An optional string specifying a path to a trace output file."
+ },
+ "buildPresets@v2": {
+ "type": "array",
+ "description": "An optional array of build preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A build preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/buildPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/buildPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/buildPresets.inherits@v2.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/buildPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/buildPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/buildPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/buildPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/buildPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/buildPresets.inheritConfigureEnvironment@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/buildPresets.jobs@v2.."
+ },
+ "targets": {
+ "$ref": "#/definitions/buildPresets.targets@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/buildPresets.configuration@v2.."
+ },
+ "cleanFirst": {
+ "$ref": "#/definitions/buildPresets.cleanFirst@v2.."
+ },
+ "verbose": {
+ "$ref": "#/definitions/buildPresets.verbose@v2.."
+ },
+ "nativeToolOptions": {
+ "$ref": "#/definitions/buildPresets.nativeToolOptions@v2.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "buildPresets@v3": {
+ "type": "array",
+ "description": "An optional array of build preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A build preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/buildPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/buildPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/buildPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/buildPresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/buildPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/buildPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/buildPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/buildPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/buildPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/buildPresets.inheritConfigureEnvironment@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/buildPresets.jobs@v2.."
+ },
+ "targets": {
+ "$ref": "#/definitions/buildPresets.targets@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/buildPresets.configuration@v2.."
+ },
+ "cleanFirst": {
+ "$ref": "#/definitions/buildPresets.cleanFirst@v2.."
+ },
+ "verbose": {
+ "$ref": "#/definitions/buildPresets.verbose@v2.."
+ },
+ "nativeToolOptions": {
+ "$ref": "#/definitions/buildPresets.nativeToolOptions@v2.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "buildPresets@v4..v9": {
+ "type": "array",
+ "description": "An optional array of build preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A build preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/buildPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/buildPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/buildPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/buildPresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/buildPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/buildPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/buildPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/buildPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/buildPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/buildPresets.inheritConfigureEnvironment@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/buildPresets.jobs@v2.."
+ },
+ "targets": {
+ "$ref": "#/definitions/buildPresets.targets@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/buildPresets.configuration@v2.."
+ },
+ "cleanFirst": {
+ "$ref": "#/definitions/buildPresets.cleanFirst@v2.."
+ },
+ "resolvePackageReferences": {
+ "$ref": "#/definitions/buildPresets.resolvePackageReferences@v4.."
+ },
+ "verbose": {
+ "$ref": "#/definitions/buildPresets.verbose@v2.."
+ },
+ "nativeToolOptions": {
+ "$ref": "#/definitions/buildPresets.nativeToolOptions@v2.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "buildPresets@v10..": {
+ "type": "array",
+ "description": "An optional array of build preset objects.",
+ "items": {
+ "type": "object",
+ "description": "A build preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/buildPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/buildPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/buildPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/buildPresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/buildPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/buildPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/buildPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/buildPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/buildPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/buildPresets.inheritConfigureEnvironment@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/buildPresets.jobs@v2.."
+ },
+ "targets": {
+ "$ref": "#/definitions/buildPresets.targets@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/buildPresets.configuration@v2.."
+ },
+ "cleanFirst": {
+ "$ref": "#/definitions/buildPresets.cleanFirst@v2.."
+ },
+ "resolvePackageReferences": {
+ "$ref": "#/definitions/buildPresets.resolvePackageReferences@v4.."
+ },
+ "verbose": {
+ "$ref": "#/definitions/buildPresets.verbose@v2.."
+ },
+ "nativeToolOptions": {
+ "$ref": "#/definitions/buildPresets.nativeToolOptions@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "buildPresets.name@v2..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the cmake --build --preset option. There must not be two build presets in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name. However, a build preset may have the same name as a configure, test, package, or workflow preset."
+ },
+ "buildPresets.hidden@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "buildPresets.inherits@v2..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of presets from which to inherit. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ }
+ }
+ ]
+ },
+ "buildPresets.condition@v3..v9": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v3..v9"
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "buildPresets.condition@v10..": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v10.."
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "buildPresets.vendor@v2..": {
+ "type": "object",
+ "minLength": 1,
+ "description": "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.",
+ "properties": {}
+ },
+ "buildPresets.displayName@v2..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "buildPresets.description@v2..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "buildPresets.environment@v2..": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ }
+ },
+ "buildPresets.configurePreset@v2..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string specifying the name of a configure preset to associate with this build preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset."
+ },
+ "buildPresets.inheritConfigureEnvironment@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited build preset environments, but before environment variables explicitly specified in this build preset."
+ },
+ "buildPresets.jobs@v2..": {
+ "type": "integer",
+ "description": "An optional non-negative integer. Equivalent to passing --parallel or -j on the command line.",
+ "minimum": 0
+ },
+ "buildPresets.targets@v2..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets.",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "buildPresets.configuration@v2..": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --config on the command line."
+ },
+ "buildPresets.cleanFirst@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --clean-first on the command line."
+ },
+ "buildPresets.resolvePackageReferences@v4..": {
+ "type": "string",
+ "enum": [
+ "on",
+ "off",
+ "only"
+ ],
+ "description": "An optional string specifying the package resolve behavior. Valid values are \"on\" (packages are resolved prior to the build), \"off\" (packages are not resolved prior to the build), and \"only\" (packages are resolved, but no build will be performed)."
+ },
+ "buildPresets.verbose@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --verbose on the command line."
+ },
+ "buildPresets.nativeToolOptions@v2..": {
+ "type": "array",
+ "description": "An optional array of strings. Equivalent to passing options after -- on the command line.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "testPresets@v2": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v2..v4"
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v2..v9"
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v2..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets@v3..v4": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/testPresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v2..v4"
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v2..v9"
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v2..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets@v5": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/testPresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v5"
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v2..v9"
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v2..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets@v6..v9": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/testPresets.condition@v3..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v6..v9"
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v2..v9"
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v2..v9"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets@v10": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/testPresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v10.."
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v10.."
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v10"
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets@v11": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/testPresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v10.."
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v10.."
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v11"
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets@v12": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest.",
+ "items": {
+ "type": "object",
+ "description": "A test preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.name@v2.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/testPresets.hidden@v2.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/testPresets.inherits@v2.."
+ },
+ "condition": {
+ "$ref": "#/definitions/testPresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/testPresets.vendor@v2.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/testPresets.displayName@v2.."
+ },
+ "description": {
+ "$ref": "#/definitions/testPresets.description@v2.."
+ },
+ "environment": {
+ "$ref": "#/definitions/testPresets.environment@v2.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/testPresets.configurePreset@v2.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/testPresets.inheritConfigureEnvironment@v2.."
+ },
+ "configuration": {
+ "$ref": "#/definitions/testPresets.configuration@v2.."
+ },
+ "overwriteConfigurationFile": {
+ "$ref": "#/definitions/testPresets.overwriteConfigurationFile@v2.."
+ },
+ "output": {
+ "$ref": "#/definitions/testPresets.output@v10.."
+ },
+ "filter": {
+ "$ref": "#/definitions/testPresets.filter@v10.."
+ },
+ "execution": {
+ "$ref": "#/definitions/testPresets.execution@v12"
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "testPresets.name@v2..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the ctest --preset option. There must not be two test presets in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name. However, a test preset may have the same name as a configure, build, package, or workflow preset."
+ },
+ "testPresets.hidden@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "testPresets.inherits@v2..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of presets from which to inherit. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ }
+ }
+ ]
+ },
+ "testPresets.condition@v3..v9": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v3..v9"
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "testPresets.condition@v10..": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v10.."
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "testPresets.vendor@v2..": {
+ "type": "object",
+ "minLength": 1,
+ "description": "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.",
+ "properties": {}
+ },
+ "testPresets.displayName@v2..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "testPresets.description@v2..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "testPresets.environment@v2..": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "propertyNames": {
+ "pattern": "^.+$"
+ },
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ }
+ },
+ "testPresets.configurePreset@v2..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string specifying the name of a configure preset to associate with this test preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build directory is inferred from the configure preset."
+ },
+ "testPresets.inheritConfigureEnvironment@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited test preset environments, but before environment variables explicitly specified in this test preset."
+ },
+ "testPresets.configuration@v2..": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --build-config on the command line."
+ },
+ "testPresets.overwriteConfigurationFile@v2..": {
+ "type": "array",
+ "description": "An optional array of configuration options to overwrite options specified in the CTest configuration file. Equivalent to passing ``--overwrite`` for each value in the array.",
+ "items": {
+ "type": "string",
+ "description": "An option written as a key-value pair in the form \"key=value\"."
+ }
+ },
+ "testPresets.output@v2..v4": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "shortProgress": {
+ "$ref": "#/definitions/testPresets.output.shortProgress@v2.."
+ },
+ "verbosity": {
+ "$ref": "#/definitions/testPresets.output.verbosity@v2.."
+ },
+ "debug": {
+ "$ref": "#/definitions/testPresets.output.debug@v2.."
+ },
+ "outputOnFailure": {
+ "$ref": "#/definitions/testPresets.output.outputOnFailure@v2.."
+ },
+ "quiet": {
+ "$ref": "#/definitions/testPresets.output.quiet@v2.."
+ },
+ "outputLogFile": {
+ "$ref": "#/definitions/testPresets.output.outputLogFile@v2.."
+ },
+ "labelSummary": {
+ "$ref": "#/definitions/testPresets.output.labelSummary@v2.."
+ },
+ "subprojectSummary": {
+ "$ref": "#/definitions/testPresets.output.subprojectSummary@v2.."
+ },
+ "maxPassedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxPassedTestOutputSize@v2.."
+ },
+ "maxFailedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxFailedTestOutputSize@v2.."
+ },
+ "maxTestNameWidth": {
+ "$ref": "#/definitions/testPresets.output.maxTestNameWidth@v2.."
+ }
+ }
+ },
+ "testPresets.output@v5": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "shortProgress": {
+ "$ref": "#/definitions/testPresets.output.shortProgress@v2.."
+ },
+ "verbosity": {
+ "$ref": "#/definitions/testPresets.output.verbosity@v2.."
+ },
+ "debug": {
+ "$ref": "#/definitions/testPresets.output.debug@v2.."
+ },
+ "outputOnFailure": {
+ "$ref": "#/definitions/testPresets.output.outputOnFailure@v2.."
+ },
+ "quiet": {
+ "$ref": "#/definitions/testPresets.output.quiet@v2.."
+ },
+ "outputLogFile": {
+ "$ref": "#/definitions/testPresets.output.outputLogFile@v2.."
+ },
+ "labelSummary": {
+ "$ref": "#/definitions/testPresets.output.labelSummary@v2.."
+ },
+ "subprojectSummary": {
+ "$ref": "#/definitions/testPresets.output.subprojectSummary@v2.."
+ },
+ "maxPassedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxPassedTestOutputSize@v2.."
+ },
+ "maxFailedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxFailedTestOutputSize@v2.."
+ },
+ "testOutputTruncation": {
+ "$ref": "#/definitions/testPresets.output.testOutputTruncation@v5.."
+ },
+ "maxTestNameWidth": {
+ "$ref": "#/definitions/testPresets.output.maxTestNameWidth@v2.."
+ }
+ }
+ },
+ "testPresets.output@v6..v9": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "shortProgress": {
+ "$ref": "#/definitions/testPresets.output.shortProgress@v2.."
+ },
+ "verbosity": {
+ "$ref": "#/definitions/testPresets.output.verbosity@v2.."
+ },
+ "debug": {
+ "$ref": "#/definitions/testPresets.output.debug@v2.."
+ },
+ "outputOnFailure": {
+ "$ref": "#/definitions/testPresets.output.outputOnFailure@v2.."
+ },
+ "quiet": {
+ "$ref": "#/definitions/testPresets.output.quiet@v2.."
+ },
+ "outputLogFile": {
+ "$ref": "#/definitions/testPresets.output.outputLogFile@v2.."
+ },
+ "outputJUnitFile": {
+ "$ref": "#/definitions/testPresets.output.outputJUnitFile@v6.."
+ },
+ "labelSummary": {
+ "$ref": "#/definitions/testPresets.output.labelSummary@v2.."
+ },
+ "subprojectSummary": {
+ "$ref": "#/definitions/testPresets.output.subprojectSummary@v2.."
+ },
+ "maxPassedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxPassedTestOutputSize@v2.."
+ },
+ "maxFailedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxFailedTestOutputSize@v2.."
+ },
+ "testOutputTruncation": {
+ "$ref": "#/definitions/testPresets.output.testOutputTruncation@v5.."
+ },
+ "maxTestNameWidth": {
+ "$ref": "#/definitions/testPresets.output.maxTestNameWidth@v2.."
+ }
+ }
+ },
+ "testPresets.output@v10..": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "shortProgress": {
+ "$ref": "#/definitions/testPresets.output.shortProgress@v2.."
+ },
+ "verbosity": {
+ "$ref": "#/definitions/testPresets.output.verbosity@v2.."
+ },
+ "debug": {
+ "$ref": "#/definitions/testPresets.output.debug@v2.."
+ },
+ "outputOnFailure": {
+ "$ref": "#/definitions/testPresets.output.outputOnFailure@v2.."
+ },
+ "quiet": {
+ "$ref": "#/definitions/testPresets.output.quiet@v2.."
+ },
+ "outputLogFile": {
+ "$ref": "#/definitions/testPresets.output.outputLogFile@v2.."
+ },
+ "outputJUnitFile": {
+ "$ref": "#/definitions/testPresets.output.outputJUnitFile@v6.."
+ },
+ "labelSummary": {
+ "$ref": "#/definitions/testPresets.output.labelSummary@v2.."
+ },
+ "subprojectSummary": {
+ "$ref": "#/definitions/testPresets.output.subprojectSummary@v2.."
+ },
+ "maxPassedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxPassedTestOutputSize@v2.."
+ },
+ "maxFailedTestOutputSize": {
+ "$ref": "#/definitions/testPresets.output.maxFailedTestOutputSize@v2.."
+ },
+ "testOutputTruncation": {
+ "$ref": "#/definitions/testPresets.output.testOutputTruncation@v5.."
+ },
+ "maxTestNameWidth": {
+ "$ref": "#/definitions/testPresets.output.maxTestNameWidth@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.output.shortProgress@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --progress on the command line."
+ },
+ "testPresets.output.verbosity@v2..": {
+ "type": "string",
+ "enum": [
+ "default",
+ "verbose",
+ "extra"
+ ],
+ "description": "An optional string specifying verbosity level. Valid values are \"default\" (equivalent to passing no verbosity flags on the command line), \"verbose\" (equivalent to passing --verbose on the command line), and \"extra\" (equivalent to passing --extra-verbose on the command line)."
+ },
+ "testPresets.output.debug@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --debug on the command line."
+ },
+ "testPresets.output.outputOnFailure@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --output-on-failure on the command line."
+ },
+ "testPresets.output.quiet@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --quiet on the command line."
+ },
+ "testPresets.output.outputLogFile@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a path to a log file. Equivalent to passing --output-log on the command line."
+ },
+ "testPresets.output.outputJUnitFile@v6..": {
+ "type": "string",
+ "description": "An optional string specifying a path to a JUnit file. Equivalent to passing --output-junit on the command line."
+ },
+ "testPresets.output.labelSummary@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If false, equivalent to passing --no-label-summary on the command line."
+ },
+ "testPresets.output.subprojectSummary@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If false, equivalent to passing --no-subproject-summary on the command line."
+ },
+ "testPresets.output.maxPassedTestOutputSize@v2..": {
+ "type": "integer",
+ "description": "An optional integer specifying the maximum output for passed tests in bytes. Equivalent to passing --test-output-size-passed on the command line."
+ },
+ "testPresets.output.maxFailedTestOutputSize@v2..": {
+ "type": "integer",
+ "description": "An optional integer specifying the maximum output for failed tests in bytes. Equivalent to passing --test-output-size-failed on the command line."
+ },
+ "testPresets.output.testOutputTruncation@v5..": {
+ "type": "string",
+ "enum": [
+ "tail",
+ "middle",
+ "head"
+ ],
+ "description": "An optional string specifying the test output truncation mode. Equivalent to passing --test-output-truncation on the command line. Must be one of the following values: \"tail\", \"middle\", or \"head\"."
+ },
+ "testPresets.output.maxTestNameWidth@v2..": {
+ "type": "integer",
+ "description": "An optional integer specifying the maximum width of a test name to output. Equivalent to passing --max-width on the command line."
+ },
+ "testPresets.filter@v2..v9": {
+ "type": "object",
+ "description": "An optional object specifying how to filter the tests to run.",
+ "properties": {
+ "include": {
+ "$ref": "#/definitions/testPresets.filter.include@v2..v9"
+ },
+ "exclude": {
+ "$ref": "#/definitions/testPresets.filter.exclude@v2..v9"
+ }
+ }
+ },
+ "testPresets.filter@v10..": {
+ "type": "object",
+ "description": "An optional object specifying how to filter the tests to run.",
+ "properties": {
+ "include": {
+ "$ref": "#/definitions/testPresets.filter.include@v10.."
+ },
+ "exclude": {
+ "$ref": "#/definitions/testPresets.filter.exclude@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.filter.include@v2..v9": {
+ "type": "object",
+ "description": "An optional object specifying which tests to include.",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.filter.include.name@v2.."
+ },
+ "label": {
+ "$ref": "#/definitions/testPresets.filter.include.label@v2.."
+ },
+ "useUnion": {
+ "$ref": "#/definitions/testPresets.filter.include.useUnion@v2.."
+ },
+ "index": {
+ "$ref": "#/definitions/testPresets.filter.include.index@v2..v9"
+ }
+ }
+ },
+ "testPresets.filter.include@v10..": {
+ "type": "object",
+ "description": "An optional object specifying which tests to include.",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.filter.include.name@v2.."
+ },
+ "label": {
+ "$ref": "#/definitions/testPresets.filter.include.label@v2.."
+ },
+ "useUnion": {
+ "$ref": "#/definitions/testPresets.filter.include.useUnion@v2.."
+ },
+ "index": {
+ "$ref": "#/definitions/testPresets.filter.include.index@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.filter.include.name@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test names. Equivalent to passing --tests-regex on the command line."
+ },
+ "testPresets.filter.include.label@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test labels. Equivalent to passing --label-regex on the command line."
+ },
+ "testPresets.filter.include.useUnion@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing --union on the command line."
+ },
+ "testPresets.filter.include.index@v2..v9": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string specifying a file with the command line syntax for --tests-information. Available in version 2 and higher."
+ },
+ {
+ "type": "object",
+ "description": "An optional object specifying test preset filters. Available in version 2 and higher.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "start": {
+ "$ref": "#/definitions/testPresets.filter.include.index.start@v2.."
+ },
+ "end": {
+ "$ref": "#/definitions/testPresets.filter.include.index.end@v2.."
+ },
+ "stride": {
+ "$ref": "#/definitions/testPresets.filter.include.index.stride@v2.."
+ },
+ "specificTests": {
+ "$ref": "#/definitions/testPresets.filter.include.index.specificTests@v2.."
+ }
+ }
+ }
+ ]
+ },
+ "testPresets.filter.include.index@v10..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string specifying a file with the command line syntax for --tests-information. Available in version 2 and higher."
+ },
+ {
+ "type": "object",
+ "description": "An optional object specifying test preset filters. Available in version 2 and higher.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "start": {
+ "$ref": "#/definitions/testPresets.filter.include.index.start@v2.."
+ },
+ "end": {
+ "$ref": "#/definitions/testPresets.filter.include.index.end@v2.."
+ },
+ "stride": {
+ "$ref": "#/definitions/testPresets.filter.include.index.stride@v2.."
+ },
+ "specificTests": {
+ "$ref": "#/definitions/testPresets.filter.include.index.specificTests@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ }
+ ]
+ },
+ "testPresets.filter.include.index.start@v2..": {
+ "type": "integer",
+ "description": "An optional integer specifying a test index at which to start testing."
+ },
+ "testPresets.filter.include.index.end@v2..": {
+ "type": "integer",
+ "description": "An optional integer specifying a test index at which to stop testing."
+ },
+ "testPresets.filter.include.index.stride@v2..": {
+ "type": "integer",
+ "description": "An optional integer specifying the increment."
+ },
+ "testPresets.filter.include.index.specificTests@v2..": {
+ "type": "array",
+ "description": "An optional array of integers specifying specific test indices to run.",
+ "items": {
+ "type": "integer",
+ "description": "An integer specifying the test to run by index."
+ }
+ },
+ "testPresets.filter.exclude@v2..v9": {
+ "type": "object",
+ "description": "An optional object specifying which tests to exclude.",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.filter.exclude.name@v2.."
+ },
+ "label": {
+ "$ref": "#/definitions/testPresets.filter.exclude.label@v2.."
+ },
+ "fixtures": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures@v2..v9"
+ }
+ }
+ },
+ "testPresets.filter.exclude@v10..": {
+ "type": "object",
+ "description": "An optional object specifying which tests to exclude.",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/testPresets.filter.exclude.name@v2.."
+ },
+ "label": {
+ "$ref": "#/definitions/testPresets.filter.exclude.label@v2.."
+ },
+ "fixtures": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.filter.exclude.name@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test names. Equivalent to passing --exclude-regex on the command line."
+ },
+ "testPresets.filter.exclude.label@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test labels. Equivalent to passing --label-exclude on the command line."
+ },
+ "testPresets.filter.exclude.fixtures@v2..v9": {
+ "type": "object",
+ "description": "An optional object specifying which fixtures to exclude from adding tests.",
+ "properties": {
+ "any": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures.any@v2.."
+ },
+ "setup": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures.setup@v2.."
+ },
+ "cleanup": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures.cleanup@v2.."
+ }
+ }
+ },
+ "testPresets.filter.exclude.fixtures@v10..": {
+ "type": "object",
+ "description": "An optional object specifying which fixtures to exclude from adding tests.",
+ "properties": {
+ "any": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures.any@v2.."
+ },
+ "setup": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures.setup@v2.."
+ },
+ "cleanup": {
+ "$ref": "#/definitions/testPresets.filter.exclude.fixtures.cleanup@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.filter.exclude.fixtures.any@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for text fixtures to exclude from adding any tests. Equivalent to passing --fixture-exclude-any on the command line."
+ },
+ "testPresets.filter.exclude.fixtures.setup@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for text fixtures to exclude from adding setup tests. Equivalent to passing --fixture-exclude-setup on the command line."
+ },
+ "testPresets.filter.exclude.fixtures.cleanup@v2..": {
+ "type": "string",
+ "description": "An optional string specifying a regex for text fixtures to exclude from adding cleanup tests. Equivalent to passing --fixture-exclude-cleanup on the command line."
+ },
+ "testPresets.execution@v2..v9": {
+ "type": "object",
+ "description": "An optional object specifying options for test execution.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "stopOnFailure": {
+ "$ref": "#/definitions/testPresets.execution.stopOnFailure@v2.."
+ },
+ "enableFailover": {
+ "$ref": "#/definitions/testPresets.execution.enableFailover@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/testPresets.execution.jobs@v2..v10"
+ },
+ "resourceSpecFile": {
+ "$ref": "#/definitions/testPresets.execution.resourceSpecFile@v2.."
+ },
+ "testLoad": {
+ "$ref": "#/definitions/testPresets.execution.testLoad@v2.."
+ },
+ "showOnly": {
+ "$ref": "#/definitions/testPresets.execution.showOnly@v2.."
+ },
+ "repeat": {
+ "$ref": "#/definitions/testPresets.execution.repeat@v2..v9"
+ },
+ "interactiveDebugging": {
+ "$ref": "#/definitions/testPresets.execution.interactiveDebugging@v2.."
+ },
+ "scheduleRandom": {
+ "$ref": "#/definitions/testPresets.execution.scheduleRandom@v2.."
+ },
+ "timeout": {
+ "$ref": "#/definitions/testPresets.execution.timeout@v2.."
+ },
+ "noTestsAction": {
+ "$ref": "#/definitions/testPresets.execution.noTestsAction@v2.."
+ }
+ }
+ },
+ "testPresets.execution@v10": {
+ "type": "object",
+ "description": "An optional object specifying options for test execution.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "stopOnFailure": {
+ "$ref": "#/definitions/testPresets.execution.stopOnFailure@v2.."
+ },
+ "enableFailover": {
+ "$ref": "#/definitions/testPresets.execution.enableFailover@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/testPresets.execution.jobs@v2..v10"
+ },
+ "resourceSpecFile": {
+ "$ref": "#/definitions/testPresets.execution.resourceSpecFile@v2.."
+ },
+ "testLoad": {
+ "$ref": "#/definitions/testPresets.execution.testLoad@v2.."
+ },
+ "showOnly": {
+ "$ref": "#/definitions/testPresets.execution.showOnly@v2.."
+ },
+ "repeat": {
+ "$ref": "#/definitions/testPresets.execution.repeat@v10.."
+ },
+ "interactiveDebugging": {
+ "$ref": "#/definitions/testPresets.execution.interactiveDebugging@v2.."
+ },
+ "scheduleRandom": {
+ "$ref": "#/definitions/testPresets.execution.scheduleRandom@v2.."
+ },
+ "timeout": {
+ "$ref": "#/definitions/testPresets.execution.timeout@v2.."
+ },
+ "noTestsAction": {
+ "$ref": "#/definitions/testPresets.execution.noTestsAction@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.execution@v11": {
+ "type": "object",
+ "description": "An optional object specifying options for test execution.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "stopOnFailure": {
+ "$ref": "#/definitions/testPresets.execution.stopOnFailure@v2.."
+ },
+ "enableFailover": {
+ "$ref": "#/definitions/testPresets.execution.enableFailover@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/testPresets.execution.jobs@v11.."
+ },
+ "resourceSpecFile": {
+ "$ref": "#/definitions/testPresets.execution.resourceSpecFile@v2.."
+ },
+ "testLoad": {
+ "$ref": "#/definitions/testPresets.execution.testLoad@v2.."
+ },
+ "showOnly": {
+ "$ref": "#/definitions/testPresets.execution.showOnly@v2.."
+ },
+ "repeat": {
+ "$ref": "#/definitions/testPresets.execution.repeat@v10.."
+ },
+ "interactiveDebugging": {
+ "$ref": "#/definitions/testPresets.execution.interactiveDebugging@v2.."
+ },
+ "scheduleRandom": {
+ "$ref": "#/definitions/testPresets.execution.scheduleRandom@v2.."
+ },
+ "timeout": {
+ "$ref": "#/definitions/testPresets.execution.timeout@v2.."
+ },
+ "noTestsAction": {
+ "$ref": "#/definitions/testPresets.execution.noTestsAction@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.execution@v12": {
+ "type": "object",
+ "description": "An optional object specifying options for test execution.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "stopOnFailure": {
+ "$ref": "#/definitions/testPresets.execution.stopOnFailure@v2.."
+ },
+ "enableFailover": {
+ "$ref": "#/definitions/testPresets.execution.enableFailover@v2.."
+ },
+ "jobs": {
+ "$ref": "#/definitions/testPresets.execution.jobs@v11.."
+ },
+ "resourceSpecFile": {
+ "$ref": "#/definitions/testPresets.execution.resourceSpecFile@v2.."
+ },
+ "testLoad": {
+ "$ref": "#/definitions/testPresets.execution.testLoad@v2.."
+ },
+ "showOnly": {
+ "$ref": "#/definitions/testPresets.execution.showOnly@v2.."
+ },
+ "repeat": {
+ "$ref": "#/definitions/testPresets.execution.repeat@v10.."
+ },
+ "interactiveDebugging": {
+ "$ref": "#/definitions/testPresets.execution.interactiveDebugging@v2.."
+ },
+ "scheduleRandom": {
+ "$ref": "#/definitions/testPresets.execution.scheduleRandom@v2.."
+ },
+ "timeout": {
+ "$ref": "#/definitions/testPresets.execution.timeout@v2.."
+ },
+ "noTestsAction": {
+ "$ref": "#/definitions/testPresets.execution.noTestsAction@v2.."
+ },
+ "testPassthroughArguments": {
+ "$ref": "#/definitions/testPresets.execution.testPassthroughArguments@v12"
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "testPresets.execution.stopOnFailure@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --stop-on-failure on the command line."
+ },
+ "testPresets.execution.enableFailover@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing -F on the command line."
+ },
+ "testPresets.execution.jobs@v2..v10": {
+ "minimum": 0,
+ "type": "integer",
+ "description": "An optional non-negative integer. Equivalent to passing --parallel or -j on the command line."
+ },
+ "testPresets.execution.jobs@v11..": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 0,
+ "description": "An optional non-negative integer. Equivalent to passing --parallel or -j on the command line."
+ },
+ {
+ "type": "string",
+ "minLength": 0,
+ "maxLength": 0,
+ "description": "An optional string. Equivalent to passing --parallel or -j on the command line with the number of jobs omitted."
+ }
+ ]
+ },
+ "testPresets.execution.resourceSpecFile@v2..": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --resource-spec-file on the command line."
+ },
+ "testPresets.execution.testLoad@v2..": {
+ "type": "integer",
+ "description": "An optional integer. Equivalent to passing --test-load on the command line."
+ },
+ "testPresets.execution.showOnly@v2..": {
+ "type": "string",
+ "enum": [
+ "human",
+ "json-v1"
+ ],
+ "description": "An optional string. Equivalent to passing --show-only on the command line. Value must be \"human\" or \"json-v1\"."
+ },
+ "testPresets.execution.repeat@v2..v9": {
+ "type": "object",
+ "description": "An optional object specifying how to repeat tests. Equivalent to passing --repeat on the command line.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "mode": {
+ "$ref": "#/definitions/testPresets.execution.repeat.mode@v2.."
+ },
+ "count": {
+ "$ref": "#/definitions/testPresets.execution.repeat.count@v2.."
+ }
+ },
+ "required": [
+ "mode",
+ "count"
+ ]
+ },
+ "testPresets.execution.repeat@v10..": {
+ "type": "object",
+ "description": "An optional object specifying how to repeat tests. Equivalent to passing --repeat on the command line.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "mode": {
+ "$ref": "#/definitions/testPresets.execution.repeat.mode@v2.."
+ },
+ "count": {
+ "$ref": "#/definitions/testPresets.execution.repeat.count@v2.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "mode",
+ "count"
+ ]
+ },
+ "testPresets.execution.repeat.mode@v2..": {
+ "type": "string",
+ "enum": [
+ "until-fail",
+ "until-pass",
+ "after-timeout"
+ ],
+ "description": "A required string. Must be one of the following values: \"until-fail\", \"until-pass\", or \"after-timeout\"."
+ },
+ "testPresets.execution.repeat.count@v2..": {
+ "type": "integer",
+ "description": "A required integer."
+ },
+ "testPresets.execution.interactiveDebugging@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --interactive-debug-mode 1 on the command line. If false, equivalent to passing --interactive-debug-mode 0 on the command line."
+ },
+ "testPresets.execution.scheduleRandom@v2..": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --schedule-random on the command line."
+ },
+ "testPresets.execution.timeout@v2..": {
+ "type": "integer",
+ "description": "An optional integer. Equivalent to passing --timeout on the command line."
+ },
+ "testPresets.execution.noTestsAction@v2..": {
+ "type": "string",
+ "enum": [
+ "default",
+ "error",
+ "ignore"
+ ],
+ "description": "An optional string specifying the behavior if no tests are found. Must be one of the following values: \"default\" (equivalent to not passing any value on the command line), \"error\" (equivalent to passing --no-tests=error on the command line), or \"ignore\" (equivalent to passing --no-tests-ignore on the command line)."
+ },
+ "testPresets.execution.testPassthroughArguments@v12": {
+ "type": "array",
+ "description": "An optional array of strings. Each element is forwarded as an argument to every test executable. Equivalent to passing arguments after -- on the ctest command line.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "packagePresets@v6..v9": {
+ "type": "array",
+ "description": "An optional array of package preset objects. Used to specify arguments to cpack.",
+ "items": {
+ "type": "object",
+ "description": "A package preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/packagePresets.name@v6.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/packagePresets.hidden@v6.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/packagePresets.inherits@v6.."
+ },
+ "condition": {
+ "$ref": "#/definitions/packagePresets.condition@v6..v9"
+ },
+ "vendor": {
+ "$ref": "#/definitions/packagePresets.vendor@v6.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/packagePresets.displayName@v6.."
+ },
+ "description": {
+ "$ref": "#/definitions/packagePresets.description@v6.."
+ },
+ "environment": {
+ "$ref": "#/definitions/packagePresets.environment@v6.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/packagePresets.configurePreset@v6.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/packagePresets.inheritConfigureEnvironment@v6.."
+ },
+ "generators": {
+ "$ref": "#/definitions/packagePresets.generators@v6.."
+ },
+ "configurations": {
+ "$ref": "#/definitions/packagePresets.configurations@v6.."
+ },
+ "variables": {
+ "$ref": "#/definitions/packagePresets.variables@v6.."
+ },
+ "configFile": {
+ "$ref": "#/definitions/packagePresets.configFile@v6.."
+ },
+ "output": {
+ "$ref": "#/definitions/packagePresets.output@v6..v9"
+ },
+ "packageName": {
+ "$ref": "#/definitions/packagePresets.packageName@v6.."
+ },
+ "packageVersion": {
+ "$ref": "#/definitions/packagePresets.packageVersion@v6.."
+ },
+ "packageDirectory": {
+ "$ref": "#/definitions/packagePresets.packageDirectory@v6.."
+ },
+ "vendorName": {
+ "$ref": "#/definitions/packagePresets.vendorName@v6.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "packagePresets@v10..": {
+ "type": "array",
+ "description": "An optional array of package preset objects. Used to specify arguments to cpack.",
+ "items": {
+ "type": "object",
+ "description": "A package preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/packagePresets.name@v6.."
+ },
+ "hidden": {
+ "$ref": "#/definitions/packagePresets.hidden@v6.."
+ },
+ "inherits": {
+ "$ref": "#/definitions/packagePresets.inherits@v6.."
+ },
+ "condition": {
+ "$ref": "#/definitions/packagePresets.condition@v10.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/packagePresets.vendor@v6.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/packagePresets.displayName@v6.."
+ },
+ "description": {
+ "$ref": "#/definitions/packagePresets.description@v6.."
+ },
+ "environment": {
+ "$ref": "#/definitions/packagePresets.environment@v6.."
+ },
+ "configurePreset": {
+ "$ref": "#/definitions/packagePresets.configurePreset@v6.."
+ },
+ "inheritConfigureEnvironment": {
+ "$ref": "#/definitions/packagePresets.inheritConfigureEnvironment@v6.."
+ },
+ "generators": {
+ "$ref": "#/definitions/packagePresets.generators@v6.."
+ },
+ "configurations": {
+ "$ref": "#/definitions/packagePresets.configurations@v6.."
+ },
+ "variables": {
+ "$ref": "#/definitions/packagePresets.variables@v6.."
+ },
+ "configFile": {
+ "$ref": "#/definitions/packagePresets.configFile@v6.."
+ },
+ "output": {
+ "$ref": "#/definitions/packagePresets.output@v10.."
+ },
+ "packageName": {
+ "$ref": "#/definitions/packagePresets.packageName@v6.."
+ },
+ "packageVersion": {
+ "$ref": "#/definitions/packagePresets.packageVersion@v6.."
+ },
+ "packageDirectory": {
+ "$ref": "#/definitions/packagePresets.packageDirectory@v6.."
+ },
+ "vendorName": {
+ "$ref": "#/definitions/packagePresets.vendorName@v6.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "packagePresets.name@v6..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the cpack --preset option. There must not be two package presets in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name. However, a package preset may have the same name as a configure, build, test, or workflow preset."
+ },
+ "packagePresets.hidden@v6..": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "packagePresets.inherits@v6..": {
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of presets from which to inherit. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string representing the name of the preset from which to inherit."
+ }
+ }
+ ]
+ },
+ "packagePresets.condition@v6..v9": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v3..v9"
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "packagePresets.condition@v10..": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/condition@v10.."
+ },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
+ },
+ "packagePresets.vendor@v6..": {
+ "type": "object",
+ "minLength": 1,
+ "description": "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.",
+ "properties": {}
+ },
+ "packagePresets.displayName@v6..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "packagePresets.description@v6..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "packagePresets.environment@v6..": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "propertyNames": {
+ "pattern": "^.+$"
+ },
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ }
+ },
+ "packagePresets.configurePreset@v6..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An optional string specifying the name of a configure preset to associate with this package preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset."
+ },
+ "packagePresets.inheritConfigureEnvironment@v6..": {
+ "type": "boolean",
+ "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited package preset environments, but before environment variables explicitly specified in this package preset."
+ },
+ "packagePresets.generators@v6..": {
+ "type": "array",
+ "description": "An optional array of strings representing generators for CPack to use.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of a CPack generator to use."
+ }
+ },
+ "packagePresets.configurations@v6..": {
+ "type": "array",
+ "description": "An optional array of strings representing build configurations for CPack to package.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of a configuration to package."
+ }
+ },
+ "packagePresets.variables@v6..": {
+ "type": "object",
+ "description": "An optional map of variables to pass to CPack, equivalent to -D arguments. Each key is the name of a variable, and the value is the string to assign to that variable.",
+ "propertyNames": {
+ "pattern": "^.+$"
+ },
+ "properties": {},
+ "additionalProperties": {
+ "type": "string",
+ "description": "An optional string representing the value of the variable."
+ }
+ },
+ "packagePresets.configFile@v6..": {
+ "type": "string",
+ "description": "An optional string representing the config file for CPack to use."
+ },
+ "packagePresets.output@v6..v9": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "debug": {
+ "$ref": "#/definitions/packagePresets.output.debug@v6.."
+ },
+ "verbose": {
+ "$ref": "#/definitions/packagePresets.output.verbose@v6.."
+ }
+ }
+ },
+ "packagePresets.output@v10..": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "debug": {
+ "$ref": "#/definitions/packagePresets.output.debug@v6.."
+ },
+ "verbose": {
+ "$ref": "#/definitions/packagePresets.output.verbose@v6.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ },
+ "packagePresets.output.debug@v6..": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not to print debug information. A value of true is equivalent to passing --debug on the command line."
+ },
+ "packagePresets.output.verbose@v6..": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not to print verbosely. A value of true is equivalent to passing --verbose on the command line."
+ },
+ "packagePresets.packageName@v6..": {
+ "type": "string",
+ "description": "An optional string representing the package name."
+ },
+ "packagePresets.packageVersion@v6..": {
+ "type": "string",
+ "description": "An optional string representing the package version."
+ },
+ "packagePresets.packageDirectory@v6..": {
+ "type": "string",
+ "description": "An optional string representing the directory in which to place the package."
+ },
+ "packagePresets.vendorName@v6..": {
+ "type": "string",
+ "description": "An optional string representing the vendor name."
+ },
+ "workflowPresets@v6..v9": {
+ "type": "array",
+ "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order.",
+ "items": {
+ "type": "object",
+ "description": "A workflow preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/workflowPresets.name@v6.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/workflowPresets.vendor@v6.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/workflowPresets.displayName@v6.."
+ },
+ "description": {
+ "$ref": "#/definitions/workflowPresets.description@v6.."
+ },
+ "steps": {
+ "$ref": "#/definitions/workflowPresets.steps@v6..v9"
+ }
+ },
+ "required": [
+ "name",
+ "steps"
+ ]
+ }
+ },
+ "workflowPresets@v10..": {
+ "type": "array",
+ "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order.",
+ "items": {
+ "type": "object",
+ "description": "A workflow preset object.",
+ "unevaluatedProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/workflowPresets.name@v6.."
+ },
+ "vendor": {
+ "$ref": "#/definitions/workflowPresets.vendor@v6.."
+ },
+ "displayName": {
+ "$ref": "#/definitions/workflowPresets.displayName@v6.."
+ },
+ "description": {
+ "$ref": "#/definitions/workflowPresets.description@v6.."
+ },
+ "steps": {
+ "$ref": "#/definitions/workflowPresets.steps@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "name",
+ "steps"
+ ]
+ }
+ },
+ "workflowPresets.name@v6..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the cmake --workflow --preset option. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name. However, a workflow preset may have the same name as a configure, build, test, or package preset."
+ },
+ "workflowPresets.vendor@v6..": {
+ "type": "object",
+ "minLength": 1,
+ "description": "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.",
+ "properties": {}
+ },
+ "workflowPresets.displayName@v6..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "workflowPresets.description@v6..": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "workflowPresets.steps@v6..v9": {
+ "type": "array",
+ "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.",
+ "items": {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/workflowPresets.steps.type@v6.."
+ },
+ "name": {
+ "$ref": "#/definitions/workflowPresets.steps.name@v6.."
+ }
+ }
+ }
+ },
+ "workflowPresets.steps@v10..": {
+ "type": "array",
+ "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.",
+ "items": {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/workflowPresets.steps.type@v6.."
+ },
+ "name": {
+ "$ref": "#/definitions/workflowPresets.steps.name@v6.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ }
+ }
+ },
+ "workflowPresets.steps.type@v6..": {
+ "type": "string",
+ "enum": [
+ "configure",
+ "build",
+ "test",
+ "package"
+ ],
+ "description": "A required string. The first step must be configure. Subsequent steps must be either build, test, or package."
+ },
+ "workflowPresets.steps.name@v6..": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A required string representing the name of the configure, build, test, or package preset to run as this workflow step."
+ },
+ "condition[1].type@v3..": {
+ "type": "string",
+ "const": "const",
+ "description": "A required string specifying the type of the condition."
+ },
+ "condition[1].value@v3..": {
+ "type": "boolean",
+ "description": "A required boolean which provides a constant value for the condition's evaluation."
+ },
+ "condition[2].type@v3..": {
+ "type": "string",
+ "enum": [
+ "equals",
+ "notEquals"
+ ],
+ "description": "A required string specifying the type of the condition."
+ },
+ "condition[2].lhs@v3..": {
+ "type": "string",
+ "description": "First string to compare. This field supports macro expansion."
+ },
+ "condition[2].rhs@v3..": {
+ "type": "string",
+ "description": "Second string to compare. This field supports macro expansion."
+ },
+ "condition[3].type@v3..": {
+ "type": "string",
+ "enum": [
+ "inList",
+ "notInList"
+ ],
+ "description": "A required string specifying the type of the condition."
+ },
+ "condition[3].string@v3..": {
+ "type": "string",
+ "description": "A required string to search for. This field supports macro expansion."
+ },
+ "condition[3].list@v3..": {
+ "type": "array",
+ "description": "A required array of strings to search. This field supports macro expansion, and uses short-circuit evaluation.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "condition[4].type@v3..": {
+ "type": "string",
+ "enum": [
+ "matches",
+ "notMatches"
+ ],
+ "description": "A required string specifying the type of the condition."
+ },
+ "condition[4].string@v3..": {
+ "type": "string",
+ "description": "A required string to search. This field supports macro expansion."
+ },
+ "condition[4].regex@v3..": {
+ "type": "string",
+ "description": "A required regular expression to search for. This field supports macro expansion."
+ },
+ "condition[5].type@v3..": {
+ "type": "string",
+ "enum": [
+ "anyOf",
+ "allOf"
+ ],
+ "description": "A required string specifying the type of the condition."
+ },
+ "condition[5].conditions@v3..v9": {
+ "type": "array",
+ "description": "A required array of condition objects. These conditions use short-circuit evaluation.",
+ "items": {
+ "$ref": "#/definitions/condition@v3..v9"
+ }
+ },
+ "condition[5].conditions@v10..": {
+ "type": "array",
+ "description": "A required array of condition objects. These conditions use short-circuit evaluation.",
+ "items": {
+ "$ref": "#/definitions/condition@v10.."
+ }
+ },
+ "condition[6].type@v3..": {
+ "type": "string",
+ "const": "not",
+ "description": "A required string specifying the type of the condition."
+ },
+ "condition[6].condition@v3..v9": {
+ "$ref": "#/definitions/condition@v3..v9"
+ },
+ "condition[6].condition@v10..": {
+ "$ref": "#/definitions/condition@v10.."
+ },
+ "condition@v3..v9": {
+ "anyOf": [
+ {
+ "type": "boolean",
+ "description": "A boolean which provides a constant value for the condition's evaluation."
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[1].type@v3.."
+ },
+ "value": {
+ "$ref": "#/definitions/condition[1].value@v3.."
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[2].type@v3.."
+ },
+ "lhs": {
+ "$ref": "#/definitions/condition[2].lhs@v3.."
+ },
+ "rhs": {
+ "$ref": "#/definitions/condition[2].rhs@v3.."
+ }
+ },
+ "required": [
+ "type",
+ "lhs",
+ "rhs"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[3].type@v3.."
+ },
+ "string": {
+ "$ref": "#/definitions/condition[3].string@v3.."
+ },
+ "list": {
+ "$ref": "#/definitions/condition[3].list@v3.."
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "list"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[4].type@v3.."
+ },
+ "string": {
+ "$ref": "#/definitions/condition[4].string@v3.."
+ },
+ "regex": {
+ "$ref": "#/definitions/condition[4].regex@v3.."
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "regex"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[5].type@v3.."
+ },
+ "conditions": {
+ "$ref": "#/definitions/condition[5].conditions@v3..v9"
+ }
+ },
+ "required": [
+ "type",
+ "conditions"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[6].type@v3.."
+ },
+ "condition": {
+ "$ref": "#/definitions/condition[6].condition@v3..v9"
+ }
+ },
+ "required": [
+ "type",
+ "condition"
+ ]
+ }
+ ]
+ },
+ "condition@v10..": {
+ "anyOf": [
+ {
+ "type": "boolean",
+ "description": "A boolean which provides a constant value for the condition's evaluation."
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[1].type@v3.."
+ },
+ "value": {
+ "$ref": "#/definitions/condition[1].value@v3.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[2].type@v3.."
+ },
+ "lhs": {
+ "$ref": "#/definitions/condition[2].lhs@v3.."
+ },
+ "rhs": {
+ "$ref": "#/definitions/condition[2].rhs@v3.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "type",
+ "lhs",
+ "rhs"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[3].type@v3.."
+ },
+ "string": {
+ "$ref": "#/definitions/condition[3].string@v3.."
+ },
+ "list": {
+ "$ref": "#/definitions/condition[3].list@v3.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "list"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[4].type@v3.."
+ },
+ "string": {
+ "$ref": "#/definitions/condition[4].string@v3.."
+ },
+ "regex": {
+ "$ref": "#/definitions/condition[4].regex@v3.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "regex"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[5].type@v3.."
+ },
+ "conditions": {
+ "$ref": "#/definitions/condition[5].conditions@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "type",
+ "conditions"
+ ]
+ },
+ {
+ "type": "object",
+ "unevaluatedProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/condition[6].type@v3.."
+ },
+ "condition": {
+ "$ref": "#/definitions/condition[6].condition@v10.."
+ },
+ "$comment": {
+ "$ref": "#/definitions/$comment@v10.."
+ }
+ },
+ "required": [
+ "type",
+ "condition"
+ ]
+ }
+ ]
}
}
}
diff --git a/Help/manual/presets/schema.yaml b/Help/manual/presets/schema.yaml
new file mode 100644
index 0000000..2a9a935
--- /dev/null
+++ b/Help/manual/presets/schema.yaml
@@ -0,0 +1,2059 @@
+---
+version: 12
+types:
+ - id: condition
+ type: variant
+ items:
+ - type: boolean
+ description:
+ A boolean which provides a constant value for the condition's
+ evaluation.
+ # 'const' condition
+ - type: object
+ unevaluatedProperties: false
+ properties:
+ type:
+ type: string
+ required: true
+ const: const
+ description:
+ A required string specifying the type of the condition.
+ value:
+ type: boolean
+ required: true
+ description:
+ A required boolean which provides a constant value for the
+ condition's evaluation.
+ # 'equals', 'notEquals' condition
+ - type: object
+ unevaluatedProperties: false
+ properties:
+ type:
+ type: string
+ required: true
+ enum:
+ - equals
+ - notEquals
+ description:
+ A required string specifying the type of the condition.
+ lhs:
+ type: string
+ required: true
+ description:
+ First string to compare. This field supports macro expansion.
+ rhs:
+ type: string
+ required: true
+ description:
+ Second string to compare. This field supports macro expansion.
+ # 'inList', 'notInList' condition
+ - type: object
+ properties:
+ type:
+ type: string
+ required: true
+ enum:
+ - inList
+ - notInList
+ description:
+ A required string specifying the type of the condition.
+ string:
+ type: string
+ required: true
+ description:
+ A required string to search for. This field supports macro
+ expansion.
+ list:
+ type: array
+ required: true
+ items:
+ type: string
+ description:
+ A required array of strings to search. This field supports macro
+ expansion, and uses short-circuit evaluation.
+ unevaluatedProperties: false
+ # 'matches', 'notMatches' condition
+ - type: object
+ properties:
+ type:
+ type: string
+ required: true
+ enum:
+ - matches
+ - notMatches
+ description:
+ A required string specifying the type of the condition.
+ string:
+ type: string
+ required: true
+ description:
+ A required string to search. This field supports macro expansion.
+ regex:
+ type: string
+ required: true
+ description:
+ A required regular expression to search for. This field supports
+ macro expansion.
+ unevaluatedProperties: false
+ # 'anyOf', 'allOf' condition
+ - type: object
+ properties:
+ type:
+ type: string
+ required: true
+ enum:
+ - anyOf
+ - allOf
+ description:
+ A required string specifying the type of the condition.
+ conditions:
+ type: array
+ required: true
+ description:
+ A required array of condition objects. These conditions use
+ short-circuit evaluation.
+ items:
+ type: ref
+ target: condition
+ unevaluatedProperties: false
+ # 'not' condition
+ - type: object
+ properties:
+ type:
+ type: string
+ required: true
+ const: not
+ description:
+ A required string specifying the type of the condition.
+ condition:
+ type: ref
+ required: true
+ target: condition
+ unevaluatedProperties: false
+definitions:
+ inherits: &preset-inherits
+ anyOf:
+ - type: string
+ minLength: 1
+ description:
+ An optional string representing the name of the preset from which to
+ inherit.
+ - type: array
+ description:
+ An optional array of strings representing the names of presets from
+ which to inherit. The preset will inherit all of the fields from the
+ inherits presets by default (except name, hidden, inherits,
+ description, and displayName), but can override them as desired. If
+ multiple inherits presets provide conflicting values for the same
+ field, the earlier preset in the inherits list will be preferred.
+ Presets in CMakePresets.json must not inherit from presets in
+ CMakeUserPresets.json.
+ items:
+ type: string
+ minLength: 1
+ description:
+ An optional string representing the name of the preset from which
+ to inherit.
+ sphinxDescription: |
+ An optional array of strings representing the names of presets from which
+ to inherit. This field can also be a string, which is equivalent to an
+ array containing one string.
+
+ The preset will inherit all of the fields from the ``inherits`` presets
+ by default (except ``name``, ``hidden``, ``inherits``, ``description``,
+ and ``displayName``), but can override them as desired. If multiple
+ ``inherits`` presets provide conflicting values for the same field, the
+ earlier preset in the ``inherits`` array will be preferred.
+
+ A preset can only inherit from another preset that is defined in the same
+ file or in one of the files it includes (directly or indirectly). Presets
+ in ``CMakePresets.json`` may not inherit from presets in
+ ``CMakeUserPresets.json``.
+ vendor: &preset-vendor
+ type: object
+ minLength: 1
+ description:
+ 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.
+ sphinxDescription: |
+ 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. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+ properties: {}
+ displayName: &preset-displayName
+ type: string
+ description:
+ An optional string with a human-friendly name of the preset.
+ description: &preset-description
+ type: string
+ description:
+ An optional string with a human-friendly description of the preset.
+ environment: &preset-environment
+ type: object
+ description: &environment-description
+ An optional map of environment variables. The key is the variable name
+ (which must not be an empty string). Each variable is set regardless of
+ whether or not a value was given to it by the process's environment. This
+ field supports macro expansion, and environment variables in this map may
+ reference each other, and may be listed in any order, as long as such
+ references do not cause a cycle (for example,if ENV_1 is $env{ENV_2},
+ ENV_2 may not be $env{ENV_1}.) Environment variables are inherited
+ through the inherits field, and the preset's environment will be the
+ union of its own environment and the environment from all its parents. If
+ multiple presets in this union define the same variable, the standard
+ rules of inherits are applied. Setting a variable to null causes it to
+ not be set, even if a value was inherited from another preset.
+ sphinxDescription: &environment-sphinx-description |
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or a
+ string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment.
+
+ This field supports `macro expansion`_, and environment variables in this
+ map may reference each other, and may be listed in any order, as long as
+ such references do not cause a cycle (for example, if ``ENV_1`` is
+ ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
+ allows one to prepend or append values to existing environment variables
+ by accessing only values from the parent environment.
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+ properties: {}
+ propertyNames:
+ pattern: '^.+$'
+ additionalProperties: &environment-additional-properties
+ anyOf:
+ - type: 'null'
+ description:
+ Setting a variable to null causes it to not be set, even if a value
+ was inherited from another preset.
+ - type: string
+ description:
+ A string representing the value of the variable.
+ architecture-or-toolset: &architecture-or-toolset-properties
+ value:
+ type: string
+ description: An optional string representing the value.
+ strategy:
+ type: string
+ enum:
+ - set
+ - external
+ description: '
+ An optional string telling CMake how to handle the field. Valid values
+ are: "set" Set the respective value. This will result in an error for
+ generators that do not support the respective field. "external" Do not
+ set the value, even if the generator supports it. This is useful if,
+ for example, a preset uses the Ninja generator, and an IDE knows how to
+ set up the Visual C++ environment from the architecture and toolset
+ fields. In that case, CMake will ignore the field, but the IDE can use
+ them to set up the environment before invoking CMake.
+ '
+ sphinxDescription: |
+ An optional string telling CMake how to handle the field.
+ Valid values are:
+
+ ``"set"``
+ Set the respective value. This will result in an error for generators
+ that do not support the respective field.
+
+ ``"external"``
+ Do not set the value, even if the generator supports it. This is
+ useful if, for example, a preset uses the Ninja generator, and an IDE
+ knows how to set up the Visual C++ environment from the architecture
+ and toolset fields. In that case, CMake will ignore the field, but
+ the IDE can use them to set up the environment before invoking CMake.
+
+ If no ``strategy`` field is given, or if the field uses the string form
+ rather than the object form, the behavior is the same as ``"set"``.
+ condition: &condition
+ since: 3
+ anyOf:
+ - type: ref
+ target: condition
+ - type: 'null'
+ description:
+ Null indicates that the condition always evaluates to true and is not
+ inherited.
+ sphinxDescription: |
+ An optional `Condition`_ object.
+description:
+ The presets specify the generator and the build directory, and optionally an
+ array of variables and other arguments to pass to CMake.
+properties:
+ $schema:
+ since: 8
+ type: string
+ format: uri-reference
+ description:
+ An optional string that provides a URI to the JSON schema that describes
+ the structure of this JSON document. This field is used for validation
+ and autocompletion in editors that support JSON schema. It doesn't affect
+ the behavior of the document itself. If this field is not specified, the
+ JSON document will still be valid, but tools that use JSON schema for
+ validation and autocompletion may not function correctly.
+ version:
+ type: integer
+ required: true
+ description:
+ A required integer representing the version of the JSON schema.
+ sphinxDescription: |
+ A required integer representing the version of the JSON schema. See
+ `Versions`_ for discussion of the supported versions and the
+ corresponding version of CMake in which they were added.
+ cmakeMinimumRequired:
+ type: object
+ description:
+ An optional object representing the minimum version of CMake
+ needed to build this project.
+ sphinxDescription: |
+ An optional object representing the minimum version of CMake
+ needed to build this project. This object consists of the following
+ fields:
+
+ .. include:: presets/cmakeMinimumRequired-properties.rst
+ properties:
+ major:
+ type: integer
+ description: An optional integer representing the major version.
+ minor:
+ type: integer
+ description: An optional integer representing the minor version.
+ patch:
+ type: integer
+ description: An optional integer representing the patch version.
+ unevaluatedProperties: false
+ include:
+ since: 4
+ type: array
+ items:
+ type: string
+ description:
+ An optional array of strings representing files to include. If the
+ filenames are not absolute, they are considered relative to the current
+ file.
+ sphinxDescription: |
+ An optional array of strings representing files to include. If the
+ filenames are not absolute, they are considered relative to the current
+ file. See `Includes`_ for discussion of the constraints on included
+ files.
+ vendor:
+ type: object
+ description:
+ 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, the keys should be a vendor-specific domain name
+ followed by a /-separated path. For example, the Example IDE 1.0 could
+ use example.com/ExampleIDE/1.0. The value of each field can be anything
+ desired by the vendor, though will typically be a map.
+ sphinxDescription: |
+ 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, the keys should be a vendor-specific domain name
+ followed by a ``/``-separated path. For example, the Example IDE 1.0
+ could use ``example.com/ExampleIDE/1.0``. The value of each field can be
+ anything desired by the vendor, though will typically be a map.
+ properties: {}
+ configurePresets:
+ type: array
+ description:
+ An optional array of configure preset objects.
+ sphinxDescription: |
+ An optional array of `Configure Preset`_ objects.
+ items:
+ type: object
+ description:
+ A configure preset object.
+ properties:
+ name:
+ type: string
+ required: true
+ minLength: 1
+ description:
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the cmake --preset option.
+ There must not be two configure presets in the union of
+ CMakePresets.json and CMakeUserPresets.json in the same directory
+ with the same name. However, a configure preset may have the same
+ name as a build, test, package, or workflow preset.
+ sphinxDescription: |
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the :option:`cmake --preset`
+ option. There must not be two configure presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a configure preset may have
+ the same name as a build, test, package, or workflow preset.
+ hidden:
+ type: boolean
+ description:
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the --preset=
+ argument, will not show up in the CMake GUI, and does not have to
+ have a valid generator or binaryDir, even from inheritance. Hidden
+ presets are intended to be used as a base for other presets to
+ inherit via the inherits field.
+ sphinxDescription: |
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :cmake-option:`--preset` argument, will not show up in the
+ :manual:`CMake GUI <cmake-gui(1)>`, and does not have to have a
+ valid ``generator`` or ``binaryDir``, even from inheritance.
+ ``hidden`` presets are intended to be used as a base for other
+ presets to inherit via the ``inherits`` field.
+ inherits: *preset-inherits
+ condition: *condition
+ vendor: *preset-vendor
+ displayName: *preset-displayName
+ description: *preset-description
+ generator:
+ revisions:
+ - until: 3
+ type: string
+ description:
+ An optional string representing the generator to use for the
+ preset. If generator is not specified, it must be inherited
+ from the inherits preset (unless this preset is hidden). Note
+ that for Visual Studio generators, unlike in the command line
+ -G argument, you cannot include the platform name in the
+ generator name. Use the architecture field instead.
+ - since: 3
+ type: string
+ description:
+ An optional string representing the generator to use for the
+ preset. If generator is not specified, the normal generator
+ discovery procedure is used. Note that for Visual Studio
+ generators, unlike in the command line -G argument, you cannot
+ include the platform name in the generator name. Use the
+ architecture field instead.
+ sphinxDescription: |
+ An optional string representing the
+ :manual:`generator <cmake-generators(7)>` to use for the preset.
+
+ .. presets-versionchanged:: 3
+
+ If omitted, CMake will fall back to regular generator discovery
+ procedure. In previous versions, if not specified, this field
+ must be inherited from the ``inherits`` preset (unless this
+ preset is ``hidden``).
+
+ Note that for :ref:`Visual Studio generators`, unlike in the
+ command line :cmake-option:`-G` argument, you cannot include the
+ platform name in the generator name. Use the ``architecture``
+ field instead.
+ architecture:
+ anyOf:
+ - type: string
+ description: &architectureDescription
+ An optional string representing the platform for generators
+ that support it.
+ - type: object
+ description: *architectureDescription
+ properties: *architecture-or-toolset-properties
+ unevaluatedProperties: false
+ sphinxDescription: |
+ Optional field representing the platform for
+ :manual:`generators <cmake-generators(7)>` that support it.
+
+ See :option:`cmake -A` for possible values.
+
+ ``architecture`` may be either a string or an object with the
+ following fields:
+
+ .. include:: presets/architecture-properties.rst
+ toolset:
+ anyOf:
+ - type: string
+ description: &toolsetDescription
+ An optional string representing the toolset for generators that
+ support it.
+ - type: object
+ description: *toolsetDescription
+ properties: *architecture-or-toolset-properties
+ unevaluatedProperties: false
+ sphinxDescription: |
+ Optional field representing the toolset for
+ :manual:`generators <cmake-generators(7)>` that support it.
+
+ See :option:`cmake -T` for possible values.
+
+ ``toolset`` may be either a string or an object with the following
+ fields:
+
+ .. include:: presets/toolset-properties.rst
+ toolchainFile:
+ since: 3
+ type: string
+ description:
+ An optional string representing the path to the toolchain file.
+ This field supports macro expansion. If a relative path is
+ specified, it is calculated relative to the build directory, and if
+ not found, relative to the source directory.
+ sphinxDescription: |
+ An optional string representing the path to the toolchain file.
+ This field supports `macro expansion`_. If a relative path is
+ specified, it is calculated relative to the build directory, and if
+ not found, relative to the source directory. This field takes
+ precedence over any :variable:`CMAKE_TOOLCHAIN_FILE` value.
+ graphviz:
+ since: 10
+ type: string
+ description:
+ An optional string specifying the path to the graphviz dot file.
+ sphinxDescription: |
+ An optional string representing the path to the graphviz input
+ file, that will contain all the library and executable dependencies
+ in the project. See the documentation for
+ :option:`cmake --graphviz` for more details.
+
+ This field supports `macro expansion`_. If a relative path is
+ specified, it is calculated relative to the current working
+ directory.
+ binaryDir:
+ revisions:
+ - until: 3
+ type: string
+ description:
+ An optional string representing the path to the output binary
+ directory. This field supports macro expansion. If a relative
+ path is specified, it is calculated relative to the source
+ directory. If binaryDir is not specified, it must be inherited
+ from the inherits preset (unless this preset is hidden).
+ - since: 3
+ type: string
+ description:
+ An optional string representing the path to the output binary
+ directory. This field supports macro expansion. If a relative
+ path is specified, it is calculated relative to the source
+ directory. If binaryDir is not specified, the path is
+ calculated using regular methods.
+ sphinxDescription: |
+ An optional string representing the path to the output binary
+ directory. This field supports `macro expansion`_. If a relative
+ path is specified, it is calculated relative to the source
+ directory.
+
+ .. presets-versionchanged:: 3
+
+ If omitted, CMake will calculate the path using regular methods.
+ In previous versions, if not specified, this field must be
+ inherited from the ``inherits`` preset (unless this preset is
+ ``hidden``).
+ installDir:
+ since: 3
+ type: string
+ description:
+ An optional string representing the path to the installation
+ directory, which will be used as the CMAKE_INSTALL_PREFIX variable.
+ This field supports macro expansion. If a relative path is
+ specified, it is calculated relative to the source directory.
+ sphinxDescription: |
+ An optional string representing the path to the installation
+ directory, which will be used as the
+ :variable:`CMAKE_INSTALL_PREFIX` variable. This field supports
+ `macro expansion`_. If a relative path is specified, it is
+ calculated relative to the source directory.
+ cmakeExecutable:
+ type: string
+ description:
+ An optional string representing the path to the CMake executable to
+ use for this preset. This is reserved for use by IDEs, and is not
+ used by CMake itself. IDEs that use this field should expand any
+ macros in it.
+ cacheVariables:
+ type: object
+ description:
+ An optional map of cache variables. The key is the variable name
+ (which must not be an empty string). Cache variables are inherited
+ through the inherits field, and the preset's variables will be the
+ union of its own cacheVariables and the cacheVariables from all its
+ parents. If multiple presets in this union define the same
+ variable, the standard rules of inherits are applied.
+ sphinxDescription: |
+ An optional map of cache variables. The key is the variable name
+ (which may not be an empty string), and the value is either
+ ``null``, a boolean (which is equivalent to a value of ``"TRUE"``
+ or ``"FALSE"`` and a type of ``BOOL``), a string representing the
+ value of the variable (which supports `macro expansion`_), or an
+ object with the following fields:
+
+ ``type``
+ An optional string representing the type of the variable.
+
+ ``value``
+ A required string or boolean representing the value of the
+ variable. A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``.
+ This field supports `macro expansion`_.
+
+ Cache variables are inherited through the ``inherits`` field, and
+ the preset's variables will be the union of its own
+ ``cacheVariables`` and the ``cacheVariables`` from all its parents.
+ If multiple presets in this union define the same variable, the
+ standard rules of ``inherits`` are applied. Setting a variable to
+ ``null`` causes it to not be set, even if a value was inherited
+ from another preset.
+ properties: {}
+ propertyNames:
+ pattern: '^.+$'
+ additionalProperties:
+ anyOf:
+ - type: 'null'
+ description:
+ Setting a variable to null causes it to not be set, even if a
+ value was inherited from another preset.
+ - type: boolean
+ description:
+ A boolean representing the value of the variable. Equivalent
+ to "TRUE" or "FALSE"
+ - type: string
+ description:
+ A string representing the value of the variable (which
+ supports macro expansion).
+ - type: object
+ description:
+ An optional object representing the cache variables for
+ generators that support it.
+ properties:
+ type:
+ type: string
+ enum:
+ - BOOL
+ - FILEPATH
+ - PATH
+ - STRING
+ - INTERNAL
+ description:
+ An optional string representing the type of the variable.
+ It should be BOOL, FILEPATH, PATH, STRING, or INTERNAL.
+ value:
+ required: true
+ anyOf:
+ - type: boolean
+ description:
+ A boolean representing the value of the variable.
+ Equivalent to "TRUE" or "FALSE".
+ - type: string
+ description:
+ A string representing the value of the variable
+ (which supports macro expansion).
+ unevaluatedProperties: false
+ environment: *preset-environment
+ warnings:
+ type: object
+ description:
+ An optional object specifying the warnings to enable.
+ sphinxDescription: |
+ An optional object specifying the warnings to enable.
+ The object may contain the following fields:
+
+ .. include:: presets/warnings-properties.rst
+ properties:
+ # These should be in lexicographical order, except for systemVars.
+ author:
+ since: 12
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing -Wauthor or
+ -Wno-author on the command line. This may not be set
+ to false if errors.author is set to true.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :option:`-Wauthor <cmake -W>` or
+ :option:`-Wno-author <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.author`` is set to ``true``.
+ deprecated:
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing -Wdeprecated or
+ -Wno-deprecated on the command line. This may not be set
+ to false if errors.deprecated is set to true.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :option:`-Wdeprecated <cmake -W>` or
+ :option:`-Wno-deprecated <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.deprecated`` is set to ``true``.
+ dev:
+ until: 12
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing -Wdev or
+ -Wno-dev on the command line. This may not be set
+ to false if errors.dev is set to true.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :option:`-Wdev <cmake -W>` or
+ :option:`-Wno-dev <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.dev`` is set to ``true``.
+ uninitialized:
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing -Wuninitialized or
+ -Wno-uninitialized on the command line. This may not be set
+ to false if errors.uninitialized is set to true.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :option:`-Wuninitialized <cmake -W>` or
+ :option:`-Wno-uninitialized <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.uninitialized`` is set to ``true``.
+ unusedCli:
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing -Wunused-cli or
+ -Wno-unused-cli on the command line. This may not be set
+ to false if errors.unusedCli is set to true.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :option:`-Wunused-cli <cmake -W>` or
+ :option:`-Wno-unused-cli <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.unusedCli`` is set to ``true``.
+ # systemVars should be last.
+ systemVars:
+ type: boolean
+ description:
+ An optional boolean. Setting this to true is equivalent to
+ passing --check-system-vars on the command line.
+ sphinxDescription: |
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--check-system-vars` on the command
+ line.
+ unevaluatedProperties: false
+ errors:
+ type: object
+ description:
+ An optional object specifying the errors to enable.
+ sphinxDescription: |
+ An optional object specifying the errors to enable.
+ The object may contain the following fields:
+
+ .. include:: presets/errors-properties.rst
+ properties:
+ # These should be in lexicographical order.
+ author:
+ since: 12
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing
+ -Werror=author or -Wno-error=author
+ on the command line. This may not be set
+ to true if warnings.author is set to false.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=author` or
+ :cmake-option:`-Wno-error=author`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.author`` is set to ``false``.
+ deprecated:
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing
+ -Werror=deprecated or -Wno-error=deprecated
+ on the command line. This may not be set
+ to true if warnings.deprecated is set to false.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=deprecated` or
+ :cmake-option:`-Wno-error=deprecated`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.deprecated`` is set to ``false``.
+ dev:
+ until: 12
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing
+ -Werror=dev or -Wno-error=dev
+ on the command line. This may not be set
+ to true if warnings.dev is set to false.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=dev` or
+ :cmake-option:`-Wno-error=dev`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.dev`` is set to ``false``.
+ uninitialized:
+ since: 12
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing
+ -Werror=uninitialized or -Wno-error=uninitialized
+ on the command line. This may not be set
+ to true if warnings.uninitialized is set to false.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=uninitialized` or
+ :cmake-option:`-Wno-error=uninitialized`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.uninitialized`` is set to ``false``.
+ unusedCli:
+ since: 12
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing
+ -Werror=unused-cli or -Wno-error=unused-cli
+ on the command line. This may not be set
+ to true if warnings.unusedCli is set to false.
+ sphinxDescription: |
+ An optional boolean. Equivalent to passing
+ :cmake-option:`-Werror=unused-cli` or
+ :cmake-option:`-Wno-error=unused-cli`
+ on the command line.
+ This may not be set to ``true``
+ if ``warnings.unusedCli`` is set to ``false``.
+ unevaluatedProperties: false
+ debug:
+ type: object
+ description:
+ An optional object specifying debug options.
+ sphinxDescription: |
+ An optional object specifying debug options.
+ The object may contain the following fields:
+
+ .. include:: presets/debug-properties.rst
+ properties:
+ output:
+ type: boolean
+ description:
+ An optional boolean. Setting this to true is equivalent to
+ passing --debug-output on the command line.
+ sphinxDescription: |
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--debug-output` on the command line.
+ tryCompile:
+ type: boolean
+ description:
+ An optional boolean. Setting this to true is equivalent to
+ passing --debug-trycompile on the command line.
+ sphinxDescription: |
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--debug-trycompile` on the command line.
+ find:
+ type: boolean
+ description:
+ An optional boolean. Setting this to true is equivalent to
+ passing --debug-find on the command line.
+ sphinxDescription: |
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--debug-find` on the command line.
+ unevaluatedProperties: false
+ trace:
+ since: 7
+ type: object
+ description:
+ An optional object specifying trace options.
+ sphinxDescription: |
+ An optional object specifying trace options.
+ The object may contain the following fields:
+
+ .. include:: presets/trace-properties.rst
+ properties:
+ mode:
+ type: string
+ enum:
+ - 'on'
+ - 'off'
+ - 'expand'
+ description:
+ An optional string that specifies the trace mode.
+ sphinxDescription: |
+ An optional string that specifies the trace mode.
+ Valid values are:
+
+ ``on``
+ Causes a trace of all calls made and from where to be
+ printed. Equivalent to passing :cmake-option:`--trace`
+ on the command line.
+
+ ``off``
+ A trace of all calls will not be printed.
+
+ ``expand``
+ Causes a trace with variables expanded of all calls made
+ and from where to be printed. Equivalent to passing
+ :cmake-option:`--trace-expand` on the command line.
+ format:
+ type: string
+ enum:
+ - human
+ - json-v1
+ description:
+ An optional string that specifies the trace output format.
+ sphinxDescription: |
+ An optional string that specifies the format output of the
+ trace. Valid values are:
+
+ ``human``
+ Prints each trace line in a human-readable format.
+ This is the default format. Equivalent to passing
+ :cmake-option:`--trace-format=human`
+ on the command line.
+
+ ``json-v1``
+ Prints each line as a separate JSON document. Equivalent
+ to passing :cmake-option:`--trace-format=json-v1`
+ on the command line.
+ source:
+ anyOf:
+ - type: string
+ minLength: 1
+ description:
+ An optional string representing the path to one source file
+ to be traced.
+ - type: array
+ description:
+ An optional array of strings representing the paths to source
+ files to be traced.
+ items:
+ type: string
+ minLength: 1
+ description:
+ A string representing the path to one source file to be
+ traced.
+ sphinxDescription: |
+ An optional array of strings representing the paths of source
+ files to be traced. This field can also be a string, which is
+ equivalent to an array containing one string. Equivalent to
+ passing :cmake-option:`--trace-source` on the command line.
+ redirect:
+ type: string
+ description:
+ An optional string specifying a path to a trace output file.
+ sphinxDescription: |
+ An optional string specifying a path to a trace output file.
+ Equivalent to passing :cmake-option:`--trace-redirect` on the
+ command line.
+ unevaluatedProperties: false
+ unevaluatedProperties: false
+ buildPresets:
+ since: 2
+ type: array
+ description:
+ An optional array of build preset objects.
+ sphinxDescription: |
+ An optional array of `Build Preset`_ objects.
+ items:
+ type: object
+ description:
+ A build preset object.
+ properties:
+ name:
+ type: string
+ required: true
+ minLength: 1
+ description:
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the cmake --build --preset
+ option. There must not be two build presets in the union of
+ CMakePresets.json and CMakeUserPresets.json in the same directory
+ with the same name. However, a build preset may have the same name
+ as a configure, test, package, or workflow preset.
+ sphinxDescription: |
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the
+ :option:`cmake --build --preset <cmake--build --preset>` option.
+ There must not be two build presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a build preset may have the
+ same name as a configure, test, package, or workflow preset.
+ hidden:
+ type: boolean
+ description:
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the --preset
+ argument and does not have to have a valid configurePreset, even
+ from inheritance. hidden presets are intended to be used as a base
+ for other presets to inherit via the inherits field.
+ sphinxDescription: |
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :cmake-build-option:`--preset` argument and does not have to have a
+ valid ``configurePreset``, even from inheritance. ``hidden``
+ presets are intended to be used as a base for other presets to
+ inherit via the ``inherits`` field.
+ inherits: *preset-inherits
+ condition: *condition
+ vendor: *preset-vendor
+ displayName: *preset-displayName
+ description: *preset-description
+ environment:
+ type: object
+ description: *environment-description
+ sphinxDescription: *environment-sphinx-description
+ sphinxNote: |
+ For a CMake project using :module:`ExternalProject` with a
+ configuration preset having environment variables needed in the
+ ExternalProject, use a build preset that inherits that
+ configuration preset or the ExternalProject will not have the
+ environment variables set in the configuration preset. Example:
+ suppose the host defaults to one compiler (say Clang) and the user
+ wishes to use another compiler (say GCC). Set configuration preset
+ environment variables :envvar:`CC` and :envvar:`CXX` and use a
+ build preset that inherits that configuration preset. Otherwise the
+ ExternalProject may use a different (system default) compiler than
+ the top-level CMake project.
+ properties: {}
+ additionalProperties: *environment-additional-properties
+ configurePreset:
+ type: string
+ minLength: 1
+ description:
+ An optional string specifying the name of a configure preset to
+ associate with this build preset. If configurePreset is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build tree directory is inferred from
+ the configure preset.
+ sphinxDescription: |
+ An optional string specifying the name of a configure preset to
+ associate with this build preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset, so the build will take place in the same
+ ``binaryDir`` that the configuration did.
+ inheritConfigureEnvironment:
+ type: boolean
+ description:
+ An optional boolean that defaults to true. If true, the environment
+ variables from the associated configure preset are inherited after
+ all inherited build preset environments, but before environment
+ variables explicitly specified in this build preset.
+ sphinxDescription: |
+ An optional boolean that defaults to ``true``. If ``true``, the
+ environment variables from the associated configure preset are
+ inherited after all inherited build preset environments, but before
+ environment variables explicitly specified in this build preset.
+ jobs:
+ type: integer
+ description:
+ An optional non-negative integer. Equivalent to passing --parallel
+ or -j on the command line.
+ sphinxDescription: |
+ An optional integer. Equivalent to passing
+ :cmake-build-option:`--parallel` or ``-j`` on the command line.
+ If the value is ``0``, it is equivalent to passing ``--parallel``
+ with ``<jobs>`` omitted; alternatively, one can define the
+ environment variable :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` as an
+ empty string using the ``environment`` field.
+
+ .. versionchanged:: 4.3
+
+ This field does not accept negative integer values, regardless of
+ the version in the preset file.
+ minimum: 0
+ targets:
+ anyOf:
+ - type: string
+ description:
+ An optional string. Equivalent to passing --target or -t on the
+ command line. Vendors may ignore the targets property or hide
+ build presets that explicitly specify targets.
+ - type: array
+ items:
+ type: string
+ description:
+ An optional array of strings. Equivalent to passing --target or
+ -t on the command line. Vendors may ignore the targets property
+ or hide build presets that explicitly specify targets.
+ sphinxDescription: |
+ An optional string or array of strings. Equivalent to passing
+ :cmake-build-option:`--target` or ``-t`` on the command line.
+ Vendors may ignore the targets property or hide build presets that
+ explicitly specify targets. This field supports `macro expansion`_.
+ configuration:
+ type: string
+ description:
+ An optional string. Equivalent to passing --config on the command
+ line.
+ sphinxDescription: |
+ An optional string. Equivalent to passing
+ :cmake-build-option:`--config` on the command line.
+ cleanFirst:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing --clean-first
+ on the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :cmake-build-option:`--clean-first` on the command line.
+ resolvePackageReferences:
+ since: 4
+ type: string
+ enum:
+ - 'on'
+ - 'off'
+ - 'only'
+ description:
+ An optional string specifying the package resolve behavior. Valid
+ values are "on" (packages are resolved prior to the build), "off"
+ (packages are not resolved prior to the build), and "only"
+ (packages are resolved, but no build will be performed).
+ sphinxDescription: |
+ An optional string that specifies the package resolve mode.
+
+ Package references are used to define dependencies to packages from
+ external package managers. Currently only NuGet in combination with
+ the :ref:`Visual Studio generators` is supported. If there are no
+ targets that define package references, this option does nothing.
+ Valid values are:
+
+ ``on``
+ Causes package references to be resolved before attempting a
+ build.
+
+ ``off``
+ Package references will not be resolved. Note that this may cause
+ errors in some build environments, such as .NET SDK style
+ projects.
+
+ ``only``
+ Only resolve package references, but do not perform a build.
+
+ .. note::
+
+ The command line parameter
+ :cmake-build-option:`--resolve-package-references`
+ will take priority over this setting. If the command line
+ parameter is not provided and this setting is not specified, an
+ environment-specific cache variable will be evaluated to decide,
+ if package restoration should be performed.
+
+ When using the :ref:`Visual Studio generators`,
+ package references are defined using the
+ :prop_tgt:`VS_PACKAGE_REFERENCES` property. Package references
+ are restored using NuGet. It can be disabled by setting the
+ :variable:`CMAKE_VS_NUGET_PACKAGE_RESTORE` variable to ``OFF``.
+ This can also be done from within a configure preset.
+ verbose:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing --verbose on
+ the command line.
+ sphinxDescription: |
+ An optional boolean. If ``true``, equivalent to passing
+ :cmake-build-option:`--verbose` on the command line.
+ nativeToolOptions:
+ type: array
+ items:
+ type: string
+ description:
+ An optional array of strings. Equivalent to passing options after
+ -- on the command line.
+ sphinxDescription: |
+ An optional array of strings. Equivalent to passing options after
+ :cmake-build-option:`--` on the command line. The array values
+ support `macro expansion`_.
+ unevaluatedProperties: false
+ testPresets:
+ since: 2
+ type: array
+ description:
+ An optional array of test preset objects. Used to specify arguments to
+ ctest.
+ sphinxDescription: |
+ An optional array of `Test Preset`_ objects.
+ items:
+ type: object
+ description:
+ A test preset object.
+ properties:
+ name:
+ type: string
+ required: true
+ minLength: 1
+ description:
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the ctest --preset option. There
+ must not be two test presets in the union of CMakePresets.json and
+ CMakeUserPresets.json in the same directory with the same name.
+ However, a test preset may have the same name as a configure,
+ build, package, or workflow preset.
+ sphinxDescription: |
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the :option:`ctest --preset`
+ option. There must not be two test presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a test preset may have the
+ same name as a configure, build, package, or workflow preset.
+ hidden:
+ type: boolean
+ description:
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the --preset
+ argument and does not have to have a valid configurePreset, even
+ from inheritance. hidden presets are intended to be used as a base
+ for other presets to inherit via the inherits field.
+ sphinxDescription: |
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :ctest-option:`--preset` argument and does not have to have a valid
+ ``configurePreset``, even from inheritance. ``hidden`` presets are
+ intended to be used as a base for other presets to inherit via the
+ ``inherits`` field.
+ inherits: *preset-inherits
+ condition: *condition
+ vendor: *preset-vendor
+ displayName: *preset-displayName
+ description: *preset-description
+ environment: *preset-environment
+ configurePreset:
+ type: string
+ minLength: 1
+ description:
+ An optional string specifying the name of a configure preset to
+ associate with this test preset. If configurePreset is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset.
+ sphinxDescription: |
+ An optional string specifying the name of a configure preset to
+ associate with this test preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset, so tests will run in the same ``binaryDir`` that
+ the configuration and build used.
+ inheritConfigureEnvironment:
+ type: boolean
+ description:
+ An optional boolean that defaults to true. If true, the environment
+ variables from the associated configure preset are inherited after
+ all inherited test preset environments, but before environment
+ variables explicitly specified in this test preset.
+ sphinxDescription: |
+ An optional boolean that defaults to ``true``. If ``true``, the
+ environment variables from the associated configure preset are
+ inherited after all inherited test preset environments, but before
+ environment variables explicitly specified in this test preset.
+ configuration:
+ type: string
+ description:
+ An optional string. Equivalent to passing --build-config on the
+ command line.
+ sphinxDescription: |
+ An optional string. Equivalent to passing
+ :ctest-option:`--build-config` on the command line.
+ overwriteConfigurationFile:
+ type: array
+ description:
+ An optional array of configuration options to overwrite options
+ specified in the CTest configuration file. Equivalent to passing
+ ``--overwrite`` for each value in the array.
+ sphinxDescription: |
+ An optional array of configuration options to overwrite options
+ specified in the CTest configuration file. Equivalent to passing
+ :ctest-option:`--overwrite` for each value in the array. The array
+ values support `macro expansion`_.
+ items:
+ type: string
+ description:
+ An option written as a key-value pair in the form "key=value".
+ output:
+ id: testOutput
+ type: object
+ description:
+ An optional object specifying output options.
+ sphinxDescription: |
+ An optional object specifying output options.
+ The object may contain the following fields:
+
+ .. include:: presets/testOutput-properties.rst
+ properties:
+ shortProgress:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing --progress
+ on the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--progress` on the command line.
+ verbosity:
+ type: string
+ enum:
+ - default
+ - verbose
+ - extra
+ description: '
+ An optional string specifying verbosity level. Valid values are
+ "default" (equivalent to passing no verbosity flags on the
+ command line), "verbose" (equivalent to passing --verbose on
+ the command line), and "extra" (equivalent to passing
+ --extra-verbose on the command line).
+ '
+ sphinxDescription: |
+ An optional string specifying verbosity level. Must be one of
+ the following:
+
+ ``default``
+ Equivalent to passing no verbosity flags on the command line.
+
+ ``verbose``
+ Equivalent to passing :ctest-option:`--verbose` on the
+ command line.
+
+ ``extra``
+ Equivalent to passing :ctest-option:`--extra-verbose` on the
+ command line.
+ debug:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing --debug on
+ the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--debug` on the command line.
+ outputOnFailure:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing
+ --output-on-failure on the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--output-on-failure` on the command line.
+ quiet:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing --quiet on
+ the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--quiet` on the command line.
+ outputLogFile:
+ type: string
+ description:
+ An optional string specifying a path to a log file. Equivalent
+ to passing --output-log on the command line.
+ sphinxDescription: |
+ An optional string specifying a path to a log file. Equivalent
+ to passing :ctest-option:`--output-log` on the command line.
+ This field supports `macro expansion`_.
+ outputJUnitFile:
+ since: 6
+ type: string
+ description:
+ An optional string specifying a path to a JUnit file.
+ Equivalent to passing --output-junit on the command line.
+ sphinxDescription: |
+ An optional string specifying a path to a JUnit file.
+ Equivalent to passing :ctest-option:`--output-junit` on the
+ command line. This field supports `macro expansion`_.
+ labelSummary:
+ type: boolean
+ description:
+ An optional boolean. If false, equivalent to passing
+ --no-label-summary on the command line.
+ sphinxDescription: |
+ An optional bool. If ``false``, equivalent to passing
+ :ctest-option:`--no-label-summary` on the command line.
+ subprojectSummary:
+ type: boolean
+ description:
+ An optional boolean. If false, equivalent to passing
+ --no-subproject-summary on the command line.
+ sphinxDescription: |
+ An optional bool. If ``false``, equivalent to passing
+ :ctest-option:`--no-subproject-summary` on the command line.
+ maxPassedTestOutputSize:
+ type: integer
+ description:
+ An optional integer specifying the maximum output for passed
+ tests in bytes. Equivalent to passing --test-output-size-passed
+ on the command line.
+ sphinxDescription: |
+ An optional integer specifying the maximum output for passed
+ tests in bytes. Equivalent to passing
+ :ctest-option:`--test-output-size-passed` on the command line.
+ maxFailedTestOutputSize:
+ type: integer
+ description:
+ An optional integer specifying the maximum output for failed
+ tests in bytes. Equivalent to passing --test-output-size-failed
+ on the command line.
+ sphinxDescription: |
+ An optional integer specifying the maximum output for failed
+ tests in bytes. Equivalent to passing
+ :ctest-option:`--test-output-size-failed` on the command line.
+ testOutputTruncation:
+ since: 5
+ type: string
+ enum:
+ - tail
+ - middle
+ - head
+ description: '
+ An optional string specifying the test output truncation mode.
+ Equivalent to passing --test-output-truncation on the command
+ line. Must be one of the following values: "tail", "middle", or
+ "head".
+ '
+ sphinxDescription: |
+ An optional string specifying the test output truncation mode.
+ Equivalent to passing :ctest-option:`--test-output-truncation`
+ on the command line. Must be one of the following values:
+
+ * ``tail``
+
+ * ``middle``
+
+ * ``head``
+ maxTestNameWidth:
+ type: integer
+ description:
+ An optional integer specifying the maximum width of a test name
+ to output. Equivalent to passing --max-width on the command
+ line.
+ sphinxDescription: |
+ An optional integer specifying the maximum width of a test name
+ to output. Equivalent to passing :ctest-option:`--max-width` on
+ the command line.
+ unevaluatedProperties: false
+ filter:
+ type: object
+ description:
+ An optional object specifying how to filter the tests to run.
+ sphinxDescription: |
+ An optional object specifying how to filter the tests to run.
+ The object may contain the following fields:
+
+ .. include:: presets/filter-properties.rst
+ properties:
+ include:
+ type: object
+ description:
+ An optional object specifying which tests to include.
+ sphinxDescription: |
+ An optional object specifying which tests to include.
+ The object may contain the following fields:
+
+ .. include:: presets/include-properties.rst
+ properties:
+ name:
+ type: string
+ description:
+ An optional string specifying a regex for test names.
+ Equivalent to passing --tests-regex on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for test names.
+ Equivalent to passing :ctest-option:`--tests-regex` on the
+ command line. This field supports `macro expansion`_.
+
+ CMake regex syntax is described under
+ :ref:`string(REGEX) <Regex Specification>`.
+ label:
+ type: string
+ description:
+ An optional string specifying a regex for test labels.
+ Equivalent to passing --label-regex on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for test labels.
+ Equivalent to passing :ctest-option:`--label-regex` on the
+ command line. This field supports `macro expansion`_.
+ useUnion:
+ type: boolean
+ description:
+ An optional boolean. Equivalent to passing --union on the
+ command line.
+ sphinxDescription: |
+ An optional bool. Equivalent to passing
+ :ctest-option:`--union` on the command line.
+ index:
+ anyOf:
+ - type: string
+ description:
+ An optional string specifying a file with the command
+ line syntax for --tests-information. Available in
+ version 2 and higher.
+ - type: object
+ description:
+ An optional object specifying test preset filters.
+ Available in version 2 and higher.
+ properties:
+ start:
+ type: integer
+ description:
+ An optional integer specifying a test index at
+ which to start testing.
+ end:
+ type: integer
+ description:
+ An optional integer specifying a test index at
+ which to stop testing.
+ stride:
+ type: integer
+ description:
+ An optional integer specifying the increment.
+ specificTests:
+ type: array
+ description:
+ An optional array of integers specifying specific
+ test indices to run.
+ items:
+ type: integer
+ description:
+ An integer specifying the test to run by index.
+ unevaluatedProperties: false
+ sphinxDescription: |
+ An optional object specifying tests to include by test
+ index. The object may contain the following fields. Can
+ also be an optional string specifying a file with the
+ command line syntax for
+ :ctest-option:`--tests-information`. If specified as a
+ string, this field supports `macro expansion`_.
+
+ .. include:: presets/index-properties.rst
+ exclude:
+ type: object
+ description:
+ An optional object specifying which tests to exclude.
+ sphinxDescription: |
+ An optional object specifying which tests to exclude.
+ The object may contain the following fields:
+
+ .. include:: presets/exclude-properties.rst
+ properties:
+ name:
+ type: string
+ description:
+ An optional string specifying a regex for test names.
+ Equivalent to passing --exclude-regex on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for test names.
+ Equivalent to passing :ctest-option:`--exclude-regex` on
+ the command line. This field supports `macro expansion`_.
+ label:
+ type: string
+ description:
+ An optional string specifying a regex for test labels.
+ Equivalent to passing --label-exclude on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for test labels.
+ Equivalent to passing :ctest-option:`--label-exclude` on
+ the command line. This field supports `macro expansion`_.
+ fixtures:
+ type: object
+ description:
+ An optional object specifying which fixtures to exclude
+ from adding tests.
+ sphinxDescription: |
+ An optional object specifying which fixtures to exclude
+ from adding tests. The object may contain the following
+ fields:
+
+ .. include:: presets/fixtures-properties.rst
+ properties:
+ any:
+ type: string
+ description:
+ An optional string specifying a regex for text fixtures
+ to exclude from adding any tests. Equivalent to passing
+ --fixture-exclude-any on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for text fixtures
+ to exclude from adding any tests. Equivalent to passing
+ :ctest-option:`--fixture-exclude-any` on the command
+ line. This field supports `macro expansion`_.
+ setup:
+ type: string
+ description:
+ An optional string specifying a regex for text fixtures
+ to exclude from adding setup tests. Equivalent to
+ passing --fixture-exclude-setup on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for text fixtures
+ to exclude from adding setup tests. Equivalent to
+ passing :ctest-option:`--fixture-exclude-setup` on the
+ command line. This field supports `macro expansion`_.
+ cleanup:
+ type: string
+ description:
+ An optional string specifying a regex for text fixtures
+ to exclude from adding cleanup tests. Equivalent to
+ passing --fixture-exclude-cleanup on the command line.
+ sphinxDescription: |
+ An optional string specifying a regex for text fixtures
+ to exclude from adding cleanup tests. Equivalent to
+ passing :ctest-option:`--fixture-exclude-cleanup` on
+ the command line.
+ This field supports `macro expansion`_.
+ execution:
+ type: object
+ description:
+ An optional object specifying options for test execution.
+ sphinxDescription: |
+ An optional object specifying options for test execution.
+ The object may contain the following fields:
+
+ .. include:: presets/execution-properties.rst
+ properties:
+ stopOnFailure:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing
+ --stop-on-failure on the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--stop-on-failure` on the command line.
+ enableFailover:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing -F on the
+ command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`-F` on the command line.
+ jobs:
+ revisions:
+ - until: 11
+ type: integer
+ minimum: 0
+ description:
+ An optional non-negative integer. Equivalent to passing
+ --parallel or -j on the command line.
+ - since: 11
+ anyOf:
+ - type: integer
+ minimum: 0
+ description:
+ An optional non-negative integer. Equivalent to passing
+ --parallel or -j on the command line.
+ - type: string
+ minLength: 0
+ maxLength: 0
+ description:
+ An optional string. Equivalent to passing --parallel or
+ -j on the command line with the number of jobs omitted.
+ sphinxDescription: |
+ An optional integer. Equivalent to passing
+ :ctest-option:`--parallel` on the command line. If the value is
+ ``0``, it is equivalent to unbounded parallelism.
+
+ .. presets-versionchanged:: 11
+
+ This field can also be a string, in which case it must be
+ empty, and is equivalent to passing ``--parallel`` with
+ ``<jobs>`` omitted.
+
+ .. versionchanged:: 4.3
+
+ This field does not accept negative integer values,
+ regardless of the version in the preset file.
+ minimum: 0
+ resourceSpecFile:
+ type: string
+ description:
+ An optional string. Equivalent to passing --resource-spec-file
+ on the command line.
+ sphinxDescription: |
+ An optional string. Equivalent to passing
+ :ctest-option:`--resource-spec-file` on the command line. This
+ field supports `macro expansion`_.
+ testLoad:
+ type: integer
+ description:
+ An optional integer. Equivalent to passing --test-load on the
+ command line.
+ sphinxDescription: |
+ An optional integer. Equivalent to passing
+ :ctest-option:`--test-load` on the command line.
+ showOnly:
+ type: string
+ enum:
+ - human
+ - json-v1
+ description:
+ An optional string. Equivalent to passing --show-only on the
+ command line. Value must be "human" or "json-v1".
+ sphinxDescription: |
+ An optional string. Equivalent to passing
+ :ctest-option:`--show-only` on the command line. The string
+ must be one of the following values:
+
+ * ``human``
+
+ * ``json-v1``
+ repeat:
+ type: object
+ description:
+ An optional object specifying how to repeat tests. Equivalent
+ to passing --repeat on the command line.
+ sphinxDescription: |
+ An optional object specifying how to repeat tests. Equivalent
+ to passing :ctest-option:`--repeat` on the command line.
+ The object must have the following fields:
+
+ .. include:: presets/repeat-properties.rst
+ properties:
+ mode:
+ type: string
+ required: true
+ enum:
+ - until-fail
+ - until-pass
+ - after-timeout
+ description: '
+ A required string. Must be one of the following values:
+ "until-fail", "until-pass", or "after-timeout".
+ '
+ sphinxDescription: |
+ A required string. Must be one of the following values:
+
+ * ``until-fail``
+
+ * ``until-pass``
+
+ * ``after-timeout``
+ count:
+ type: integer
+ required: true
+ description:
+ A required integer.
+ unevaluatedProperties: false
+ interactiveDebugging:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing
+ --interactive-debug-mode 1 on the command line. If false,
+ equivalent to passing --interactive-debug-mode 0 on the
+ command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--interactive-debug-mode 1` on the command line.
+ If ``false``, equivalent to passing
+ :ctest-option:`--interactive-debug-mode 0` on the command line.
+ scheduleRandom:
+ type: boolean
+ description:
+ An optional boolean. If true, equivalent to passing
+ --schedule-random on the command line.
+ sphinxDescription: |
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--schedule-random` on the command line.
+ timeout:
+ type: integer
+ description:
+ An optional integer. Equivalent to passing --timeout on the
+ command line.
+ sphinxDescription: |
+ An optional integer. Equivalent to passing
+ :ctest-option:`--timeout` on the command line.
+ noTestsAction:
+ type: string
+ enum:
+ - default
+ - error
+ - ignore
+ description: '
+ An optional string specifying the behavior if no tests are
+ found. Must be one of the following values: "default"
+ (equivalent to not passing any value on the command line),
+ "error" (equivalent to passing --no-tests=error on the command
+ line), or "ignore" (equivalent to passing --no-tests-ignore on
+ the command line).
+ '
+ sphinxDescription: |
+ An optional string specifying the behavior if no tests are
+ found. Must be one of the following values:
+
+ ``default``
+ Equivalent to not passing any value on the command line.
+
+ ``error``
+ Equivalent to passing :ctest-option:`--no-tests=error`
+ on the command line.
+
+ ``ignore``
+ Equivalent to passing :ctest-option:`--no-tests=ignore`
+ on the command line.
+ testPassthroughArguments:
+ since: 12
+ type: array
+ items:
+ type: string
+ description:
+ An optional array of strings. Each element is forwarded as an
+ argument to every test executable. Equivalent to passing
+ arguments after -- on the ctest command line.
+ sphinxDescription: |
+ An optional array of strings. Each element is forwarded as an
+ argument to every test executable, equivalent to passing
+ arguments after :option:`ctest --` on the command line.
+
+ When both preset and command-line passthrough arguments are
+ specified, preset arguments appear first, followed by
+ command-line arguments.
+ unevaluatedProperties: false
+ unevaluatedProperties: false
+ packagePresets:
+ since: 6
+ type: array
+ description:
+ An optional array of package preset objects. Used to specify arguments to
+ cpack.
+ sphinxDescription: |
+ An optional array of `Package Preset`_ objects.
+ items:
+ type: object
+ description:
+ A package preset object.
+ properties:
+ name:
+ type: string
+ required: true
+ minLength: 1
+ description:
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the cpack --preset option. There
+ must not be two package presets in the union of CMakePresets.json
+ and CMakeUserPresets.json in the same directory with the same name.
+ However, a package preset may have the same name as a configure,
+ build, test, or workflow preset.
+ sphinxDescription: |
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the :option:`cpack --preset`
+ option. There must not be two package presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a package preset may have
+ the same name as a configure, build, test, or workflow preset.
+ hidden:
+ type: boolean
+ description:
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the --preset
+ argument and does not have to have a valid configurePreset, even
+ from inheritance. hidden presets are intended to be used as a base
+ for other presets to inherit via the inherits field.
+ sphinxDescription: |
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :cpack-option:`--preset` argument and does not have to have a valid
+ ``configurePreset``, even from inheritance. ``hidden`` presets are
+ intended to be used as a base for other presets to inherit via the
+ ``inherits`` field.
+ inherits: *preset-inherits
+ condition: *condition
+ vendor: *preset-vendor
+ displayName: *preset-displayName
+ description: *preset-description
+ environment: *preset-environment
+ configurePreset:
+ type: string
+ minLength: 1
+ description:
+ An optional string specifying the name of a configure preset to
+ associate with this package preset. If configurePreset is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build tree directory is inferred from
+ the configure preset.
+ sphinxDescription: |
+ An optional string specifying the name of a configure preset to
+ associate with this package preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset, so packaging will run in the same ``binaryDir``
+ that the configuration did and build did.
+ inheritConfigureEnvironment:
+ type: boolean
+ description:
+ An optional boolean that defaults to true. If true, the environment
+ variables from the associated configure preset are inherited after
+ all inherited package preset environments, but before environment
+ variables explicitly specified in this package preset.
+ sphinxDescription: |
+ An optional boolean that defaults to ``true``. If ``true``, the
+ environment variables from the associated configure preset are
+ inherited after all inherited package preset environments, but
+ before environment variables explicitly specified in this package
+ preset.
+ generators:
+ type: array
+ description:
+ An optional array of strings representing generators for CPack to
+ use.
+ items:
+ type: string
+ description:
+ An optional string representing the name of a CPack generator
+ to use.
+ configurations:
+ type: array
+ description:
+ An optional array of strings representing build configurations for
+ CPack to package.
+ items:
+ type: string
+ description:
+ An optional string representing the name of a configuration to
+ package.
+ variables:
+ type: object
+ description:
+ An optional map of variables to pass to CPack, equivalent to -D
+ arguments. Each key is the name of a variable, and the value is the
+ string to assign to that variable.
+ sphinxDescription: |
+ An optional map of variables to pass to CPack, equivalent to
+ :cpack-option:`-D` arguments. Each key is the name of a variable,
+ and the value is the string to assign to that variable.
+ properties: {}
+ propertyNames:
+ pattern: '^.+$'
+ additionalProperties:
+ type: string
+ description:
+ An optional string representing the value of the variable.
+ configFile:
+ type: string
+ description:
+ An optional string representing the config file for CPack to use.
+ output:
+ id: packageOutput
+ type: object
+ description:
+ An optional object specifying output options.
+ sphinxDescription: |
+ An optional object specifying output options. Valid keys are:
+
+ .. include:: presets/packageOutput-properties.rst
+ properties:
+ debug:
+ type: boolean
+ description:
+ An optional boolean specifying whether or not to print debug
+ information. A value of true is equivalent to passing --debug
+ on the command line.
+ sphinxDescription: |
+ An optional boolean specifying whether or not to print debug
+ information. A value of ``true`` is equivalent to passing
+ :cpack-option:`--debug` on the command line.
+ verbose:
+ type: boolean
+ description:
+ An optional boolean specifying whether or not to print
+ verbosely. A value of true is equivalent to passing --verbose
+ on the command line.
+ sphinxDescription: |
+ An optional boolean specifying whether or not to print
+ verbosely. A value of ``true`` is equivalent to passing
+ :cpack-option:`--verbose` on the command line.
+ unevaluatedProperties: false
+ packageName:
+ type: string
+ description:
+ An optional string representing the package name.
+ sphinxNote: &package-naming-note |
+ Due to problems with the implementation, this field does not affect
+ the name of the final package file produced. However, other aspects
+ of the package may use the value, leading to inconsistencies. A
+ future CMake release may address this problem, but until then, it
+ is recommended that this field not be used.
+ packageVersion:
+ type: string
+ description:
+ An optional string representing the package version.
+ sphinxNote: *package-naming-note
+ packageDirectory:
+ type: string
+ description:
+ An optional string representing the directory in which to place the
+ package.
+ vendorName:
+ type: string
+ description:
+ An optional string representing the vendor name.
+ unevaluatedProperties: false
+ workflowPresets:
+ since: 6
+ type: array
+ description:
+ An optional array of workflow preset objects. Used to execute configure,
+ build, test, and package presets in order.
+ sphinxDescription: |
+ An optional array of `Workflow Preset`_ objects.
+ items:
+ type: object
+ description:
+ A workflow preset object.
+ properties:
+ name:
+ type: string
+ required: true
+ minLength: 1
+ description:
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the cmake --workflow --preset
+ option. There must not be two presets (configure, build, test,
+ package, or workflow) in the union of CMakePresets.json and
+ CMakeUserPresets.json in the same directory with the same name.
+ However, a workflow preset may have the same name as a configure,
+ build, test, or package preset.
+ sphinxDescription: |
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the
+ :option:`cmake --workflow --preset <cmake--workflow --preset>`
+ option. There must not be two workflow presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a workflow preset may have
+ the same name as a configure, build, test, or package preset.
+ vendor: *preset-vendor
+ displayName: *preset-displayName
+ description: *preset-description
+ steps:
+ type: array
+ required: true
+ description:
+ A required array of objects describing the steps of the workflow.
+ The first step must be a configure preset, and all subsequent steps
+ must be non-configure presets whose configurePreset field matches
+ the starting configure preset.
+ sphinxDescription: |
+ A required array of objects describing the steps of the workflow.
+ The first step must be a configure preset, and all subsequent steps
+ must be non-configure presets whose ``configurePreset`` field
+ matches the starting configure preset. Each object may contain the
+ following fields:
+
+ .. include:: presets/steps-properties.rst
+ items:
+ type: object
+ properties:
+ type:
+ type: string
+ enum:
+ - configure
+ - build
+ - test
+ - package
+ description:
+ A required string. The first step must be configure.
+ Subsequent steps must be either build, test, or package.
+ sphinxDescription: |
+ A required string. The first step must be ``configure``.
+ Subsequent steps must be either ``build``, ``test``, or
+ ``package``.
+ name:
+ type: string
+ minLength: 1
+ description:
+ A required string representing the name of the configure,
+ build, test, or package preset to run as this workflow step.
+ unevaluatedProperties: false
+ unevaluatedProperties: false
+additionalProperties: false
diff --git a/Help/manual/presets/steps-properties.rst b/Help/manual/presets/steps-properties.rst
new file mode 100644
index 0000000..6da4a51
--- /dev/null
+++ b/Help/manual/presets/steps-properties.rst
@@ -0,0 +1,14 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.workflowPresets.steps.type`:
+
+``type``
+ A required string. The first step must be ``configure``.
+ Subsequent steps must be either ``build``, ``test``, or
+ ``package``.
+
+.. _`CMakePresets.workflowPresets.steps.name`:
+
+``name``
+ A required string representing the name of the configure, build, test, or package preset to run as this workflow step.
diff --git a/Help/manual/presets/testOutput-properties.rst b/Help/manual/presets/testOutput-properties.rst
new file mode 100644
index 0000000..3e5a6df
--- /dev/null
+++ b/Help/manual/presets/testOutput-properties.rst
@@ -0,0 +1,107 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.output.shortProgress`:
+
+``shortProgress``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--progress` on the command line.
+
+.. _`CMakePresets.testPresets.output.verbosity`:
+
+``verbosity``
+ An optional string specifying verbosity level. Must be one of
+ the following:
+
+ ``default``
+ Equivalent to passing no verbosity flags on the command line.
+
+ ``verbose``
+ Equivalent to passing :ctest-option:`--verbose` on the
+ command line.
+
+ ``extra``
+ Equivalent to passing :ctest-option:`--extra-verbose` on the
+ command line.
+
+.. _`CMakePresets.testPresets.output.debug`:
+
+``debug``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--debug` on the command line.
+
+.. _`CMakePresets.testPresets.output.outputOnFailure`:
+
+``outputOnFailure``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--output-on-failure` on the command line.
+
+.. _`CMakePresets.testPresets.output.quiet`:
+
+``quiet``
+ An optional bool. If ``true``, equivalent to passing
+ :ctest-option:`--quiet` on the command line.
+
+.. _`CMakePresets.testPresets.output.outputLogFile`:
+
+``outputLogFile``
+ An optional string specifying a path to a log file. Equivalent
+ to passing :ctest-option:`--output-log` on the command line.
+ This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.output.outputJUnitFile`:
+
+``outputJUnitFile``
+ .. presets-versionadded:: 6
+
+ An optional string specifying a path to a JUnit file.
+ Equivalent to passing :ctest-option:`--output-junit` on the
+ command line. This field supports `macro expansion`_.
+
+.. _`CMakePresets.testPresets.output.labelSummary`:
+
+``labelSummary``
+ An optional bool. If ``false``, equivalent to passing
+ :ctest-option:`--no-label-summary` on the command line.
+
+.. _`CMakePresets.testPresets.output.subprojectSummary`:
+
+``subprojectSummary``
+ An optional bool. If ``false``, equivalent to passing
+ :ctest-option:`--no-subproject-summary` on the command line.
+
+.. _`CMakePresets.testPresets.output.maxPassedTestOutputSize`:
+
+``maxPassedTestOutputSize``
+ An optional integer specifying the maximum output for passed
+ tests in bytes. Equivalent to passing
+ :ctest-option:`--test-output-size-passed` on the command line.
+
+.. _`CMakePresets.testPresets.output.maxFailedTestOutputSize`:
+
+``maxFailedTestOutputSize``
+ An optional integer specifying the maximum output for failed
+ tests in bytes. Equivalent to passing
+ :ctest-option:`--test-output-size-failed` on the command line.
+
+.. _`CMakePresets.testPresets.output.testOutputTruncation`:
+
+``testOutputTruncation``
+ .. presets-versionadded:: 5
+
+ An optional string specifying the test output truncation mode.
+ Equivalent to passing :ctest-option:`--test-output-truncation`
+ on the command line. Must be one of the following values:
+
+ * ``tail``
+
+ * ``middle``
+
+ * ``head``
+
+.. _`CMakePresets.testPresets.output.maxTestNameWidth`:
+
+``maxTestNameWidth``
+ An optional integer specifying the maximum width of a test name
+ to output. Equivalent to passing :ctest-option:`--max-width` on
+ the command line.
diff --git a/Help/manual/presets/testPresets-properties.rst b/Help/manual/presets/testPresets-properties.rst
new file mode 100644
index 0000000..293d88f
--- /dev/null
+++ b/Help/manual/presets/testPresets-properties.rst
@@ -0,0 +1,146 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.testPresets.name`:
+
+``name``
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the :option:`ctest --preset`
+ option. There must not be two test presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a test preset may have the
+ same name as a configure, build, package, or workflow preset.
+
+.. _`CMakePresets.testPresets.hidden`:
+
+``hidden``
+ An optional boolean specifying whether or not a preset should be
+ hidden. If a preset is hidden, it cannot be used in the
+ :ctest-option:`--preset` argument and does not have to have a valid
+ ``configurePreset``, even from inheritance. ``hidden`` presets are
+ intended to be used as a base for other presets to inherit via the
+ ``inherits`` field.
+
+.. _`CMakePresets.testPresets.inherits`:
+
+``inherits``
+ An optional array of strings representing the names of presets from which
+ to inherit. This field can also be a string, which is equivalent to an
+ array containing one string.
+
+ The preset will inherit all of the fields from the ``inherits`` presets
+ by default (except ``name``, ``hidden``, ``inherits``, ``description``,
+ and ``displayName``), but can override them as desired. If multiple
+ ``inherits`` presets provide conflicting values for the same field, the
+ earlier preset in the ``inherits`` array will be preferred.
+
+ A preset can only inherit from another preset that is defined in the same
+ file or in one of the files it includes (directly or indirectly). Presets
+ in ``CMakePresets.json`` may not inherit from presets in
+ ``CMakeUserPresets.json``.
+
+.. _`CMakePresets.testPresets.condition`:
+
+``condition``
+ .. presets-versionadded:: 3
+
+ An optional `Condition`_ object.
+
+.. _`CMakePresets.testPresets.vendor`:
+
+``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. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+.. _`CMakePresets.testPresets.displayName`:
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
+
+.. _`CMakePresets.testPresets.description`:
+
+``description``
+ An optional string with a human-friendly description of the preset.
+
+.. _`CMakePresets.testPresets.environment`:
+
+``environment``
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or a
+ string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment.
+
+ This field supports `macro expansion`_, and environment variables in this
+ map may reference each other, and may be listed in any order, as long as
+ such references do not cause a cycle (for example, if ``ENV_1`` is
+ ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``). ``$penv{NAME}``
+ allows one to prepend or append values to existing environment variables
+ by accessing only values from the parent environment.
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+.. _`CMakePresets.testPresets.configurePreset`:
+
+``configurePreset``
+ An optional string specifying the name of a configure preset to
+ associate with this test preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless
+ this preset is hidden). The build directory is inferred from the
+ configure preset, so tests will run in the same ``binaryDir`` that
+ the configuration and build used.
+
+.. _`CMakePresets.testPresets.inheritConfigureEnvironment`:
+
+``inheritConfigureEnvironment``
+ An optional boolean that defaults to ``true``. If ``true``, the
+ environment variables from the associated configure preset are
+ inherited after all inherited test preset environments, but before
+ environment variables explicitly specified in this test preset.
+
+.. _`CMakePresets.testPresets.configuration`:
+
+``configuration``
+ An optional string. Equivalent to passing
+ :ctest-option:`--build-config` on the command line.
+
+.. _`CMakePresets.testPresets.overwriteConfigurationFile`:
+
+``overwriteConfigurationFile``
+ An optional array of configuration options to overwrite options
+ specified in the CTest configuration file. Equivalent to passing
+ :ctest-option:`--overwrite` for each value in the array. The array
+ values support `macro expansion`_.
+
+.. _`CMakePresets.testPresets.output`:
+
+``output``
+ An optional object specifying output options.
+ The object may contain the following fields:
+
+ .. include:: presets/testOutput-properties.rst
+
+.. _`CMakePresets.testPresets.filter`:
+
+``filter``
+ An optional object specifying how to filter the tests to run.
+ The object may contain the following fields:
+
+ .. include:: presets/filter-properties.rst
+
+.. _`CMakePresets.testPresets.execution`:
+
+``execution``
+ An optional object specifying options for test execution.
+ The object may contain the following fields:
+
+ .. include:: presets/execution-properties.rst
diff --git a/Help/manual/presets/toolset-properties.rst b/Help/manual/presets/toolset-properties.rst
new file mode 100644
index 0000000..1fc91ca
--- /dev/null
+++ b/Help/manual/presets/toolset-properties.rst
@@ -0,0 +1,27 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.toolset.value`:
+
+``value``
+ An optional string representing the value.
+
+.. _`CMakePresets.configurePresets.toolset.strategy`:
+
+``strategy``
+ An optional string telling CMake how to handle the field.
+ Valid values are:
+
+ ``"set"``
+ Set the respective value. This will result in an error for generators
+ that do not support the respective field.
+
+ ``"external"``
+ Do not set the value, even if the generator supports it. This is
+ useful if, for example, a preset uses the Ninja generator, and an IDE
+ knows how to set up the Visual C++ environment from the architecture
+ and toolset fields. In that case, CMake will ignore the field, but
+ the IDE can use them to set up the environment before invoking CMake.
+
+ If no ``strategy`` field is given, or if the field uses the string form
+ rather than the object form, the behavior is the same as ``"set"``.
diff --git a/Help/manual/presets/trace-properties.rst b/Help/manual/presets/trace-properties.rst
new file mode 100644
index 0000000..b7b8b94
--- /dev/null
+++ b/Help/manual/presets/trace-properties.rst
@@ -0,0 +1,53 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.trace.mode`:
+
+``mode``
+ An optional string that specifies the trace mode.
+ Valid values are:
+
+ ``on``
+ Causes a trace of all calls made and from where to be
+ printed. Equivalent to passing :cmake-option:`--trace`
+ on the command line.
+
+ ``off``
+ A trace of all calls will not be printed.
+
+ ``expand``
+ Causes a trace with variables expanded of all calls made
+ and from where to be printed. Equivalent to passing
+ :cmake-option:`--trace-expand` on the command line.
+
+.. _`CMakePresets.configurePresets.trace.format`:
+
+``format``
+ An optional string that specifies the format output of the
+ trace. Valid values are:
+
+ ``human``
+ Prints each trace line in a human-readable format.
+ This is the default format. Equivalent to passing
+ :cmake-option:`--trace-format=human`
+ on the command line.
+
+ ``json-v1``
+ Prints each line as a separate JSON document. Equivalent
+ to passing :cmake-option:`--trace-format=json-v1`
+ on the command line.
+
+.. _`CMakePresets.configurePresets.trace.source`:
+
+``source``
+ An optional array of strings representing the paths of source
+ files to be traced. This field can also be a string, which is
+ equivalent to an array containing one string. Equivalent to
+ passing :cmake-option:`--trace-source` on the command line.
+
+.. _`CMakePresets.configurePresets.trace.redirect`:
+
+``redirect``
+ An optional string specifying a path to a trace output file.
+ Equivalent to passing :cmake-option:`--trace-redirect` on the
+ command line.
diff --git a/Help/manual/presets/warnings-properties.rst b/Help/manual/presets/warnings-properties.rst
new file mode 100644
index 0000000..8a89778
--- /dev/null
+++ b/Help/manual/presets/warnings-properties.rst
@@ -0,0 +1,63 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.configurePresets.warnings.author`:
+
+``author``
+ .. presets-versionadded:: 12
+
+ An optional boolean. Equivalent to passing
+ :option:`-Wauthor <cmake -W>` or
+ :option:`-Wno-author <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.author`` is set to ``true``.
+
+.. _`CMakePresets.configurePresets.warnings.deprecated`:
+
+``deprecated``
+ An optional boolean. Equivalent to passing
+ :option:`-Wdeprecated <cmake -W>` or
+ :option:`-Wno-deprecated <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.deprecated`` is set to ``true``.
+
+.. _`CMakePresets.configurePresets.warnings.dev`:
+
+``dev``
+ .. presets-versionremoved:: 12
+
+ An optional boolean. Equivalent to passing
+ :option:`-Wdev <cmake -W>` or
+ :option:`-Wno-dev <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.dev`` is set to ``true``.
+
+.. _`CMakePresets.configurePresets.warnings.uninitialized`:
+
+``uninitialized``
+ An optional boolean. Equivalent to passing
+ :option:`-Wuninitialized <cmake -W>` or
+ :option:`-Wno-uninitialized <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.uninitialized`` is set to ``true``.
+
+.. _`CMakePresets.configurePresets.warnings.unusedCli`:
+
+``unusedCli``
+ An optional boolean. Equivalent to passing
+ :option:`-Wunused-cli <cmake -W>` or
+ :option:`-Wno-unused-cli <cmake -Wno->`
+ on the command line.
+ This may not be set to ``false``
+ if ``errors.unusedCli`` is set to ``true``.
+
+.. _`CMakePresets.configurePresets.warnings.systemVars`:
+
+``systemVars``
+ An optional boolean. Setting this to ``true`` is equivalent to
+ passing :cmake-option:`--check-system-vars` on the command
+ line.
diff --git a/Help/manual/presets/workflowPresets-properties.rst b/Help/manual/presets/workflowPresets-properties.rst
new file mode 100644
index 0000000..fdebe96
--- /dev/null
+++ b/Help/manual/presets/workflowPresets-properties.rst
@@ -0,0 +1,44 @@
+.. This file was generated by Utilities/Scripts/regenerate-presets.py
+ from Help/manual/presets/schema.yaml. Do not edit.
+
+.. _`CMakePresets.workflowPresets.name`:
+
+``name``
+ A required string representing the machine-friendly name of the
+ preset. This identifier is used in the
+ :option:`cmake --workflow --preset <cmake--workflow --preset>`
+ option. There must not be two workflow presets in the union of
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same
+ directory with the same name. However, a workflow preset may have
+ the same name as a configure, build, test, or package preset.
+
+.. _`CMakePresets.workflowPresets.vendor`:
+
+``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. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+.. _`CMakePresets.workflowPresets.displayName`:
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
+
+.. _`CMakePresets.workflowPresets.description`:
+
+``description``
+ An optional string with a human-friendly description of the preset.
+
+.. _`CMakePresets.workflowPresets.steps`:
+
+``steps``
+ A required array of objects describing the steps of the workflow.
+ The first step must be a configure preset, and all subsequent steps
+ must be non-configure presets whose ``configurePreset`` field
+ matches the starting configure preset. Each object may contain the
+ following fields:
+
+ .. include:: presets/steps-properties.rst
diff --git a/Help/policy/CMP0211.rst b/Help/policy/CMP0211.rst
new file mode 100644
index 0000000..4ef04c8
--- /dev/null
+++ b/Help/policy/CMP0211.rst
@@ -0,0 +1,22 @@
+CMP0211
+-------
+
+.. versionadded:: 4.4
+
+A file may belong to at most one :ref:`file set <file sets>` in a target.
+
+In CMake 4.3 and below, it was possible to specify the same file
+in multiple file sets in a target. In CMake 4.4 and above, a file
+may belong to at most one file set in a target. This policy provides
+compatibility for projects that have not been updated accordingly.
+
+The ``OLD`` behavior for this policy is to accept the same file in
+multiple file sets in a target. The ``NEW`` behavior for this policy
+is to accept a given file in at most one file set in a target.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4
+.. |WARNS_OR_DOES_NOT_WARN| replace::
+ warns when a file is part of multiple file sets in a target
+.. include:: include/STANDARD_ADVICE.rst
+
+.. include:: include/DEPRECATED.rst
diff --git a/Help/policy/CMP0212.rst b/Help/policy/CMP0212.rst
new file mode 100644
index 0000000..81d7828
--- /dev/null
+++ b/Help/policy/CMP0212.rst
@@ -0,0 +1,31 @@
+CMP0212
+-------
+
+.. versionadded:: 4.4
+
+:command:`add_custom_command` ``DEPENDS`` does not strip ``.exe`` suffixes.
+
+When searching for dependencies specified with the ``DEPENDS`` option of
+:command:`add_custom_command`, CMake 4.3 and below applied a heuristic to
+remove ``.exe`` from the end of ``DEPENDS`` argument values, which created a
+target-level dependency on an executable with that stripped name if such a
+target exists. This allowed using the name of the target output file as an
+alternative spelling when naming dependencies. However, with the emergence of
+CMake's target model, specifying the output file in this way is no longer
+needed, and leads to conflicts in creating target- and file-level dependencies
+when targets exist with the ``.exe`` suffix in the name itself.
+
+The ``OLD`` behavior of this policy strips the ``.exe`` suffix from arguments
+to ``DEPENDS`` when searching for target-level dependencies. The ``NEW``
+behavior does not strip the ``.exe`` suffix in its search. CMake will otherwise
+proceed normally with the other dependency search heuristics as specified in
+:command:`add_custom_command` ``DEPENDS``. Users are encouraged to specify the
+name of the executable target if a target-level dependency is desired, or use
+the :genex:`TARGET_FILE` generator expression if a file-level dependency
+is desired, rather than implying the target indirectly via its output file name.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: include/STANDARD_ADVICE.rst
+
+.. include:: include/DEPRECATED.rst
diff --git a/Help/policy/CMP0213.rst b/Help/policy/CMP0213.rst
new file mode 100644
index 0000000..d8a8e25
--- /dev/null
+++ b/Help/policy/CMP0213.rst
@@ -0,0 +1,22 @@
+CMP0213
+-------
+
+.. versionadded:: 4.4
+
+:command:`file(ARCHIVE_CREATE)` and :command:`file(ARCHIVE_EXTRACT)`
+encode archive paths as UTF-8 by default.
+
+CMake 4.3 and below always used the ``OEM`` (current locale) encoding for archive
+paths. CMake 4.4 offer the ``ENCODING`` option, but prefer to use ``UTF-8``
+by default. This policy provides compatibility for projects that have not
+been updated to specify the encoding or accept the new default.
+
+The ``OLD`` behavior for this policy is to use the current locale as the
+default encoding, which is also known as an ``OEM`` encoding.
+The ``NEW`` behavior uses ``UTF-8`` as the default encoding.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: include/STANDARD_ADVICE.rst
+
+.. include:: include/DEPRECATED.rst
diff --git a/Help/prop_fs/BASE_DIRS.rst b/Help/prop_fs/BASE_DIRS.rst
new file mode 100644
index 0000000..879d44d
--- /dev/null
+++ b/Help/prop_fs/BASE_DIRS.rst
@@ -0,0 +1,15 @@
+BASE_DIRS
+---------
+
+.. versionadded:: 4.4
+
+List of base directories of the file set. The :command:`target_sources` command
+sets or adds to the ``BASE_DIRS`` file set property and is the usual way to
+manipulate it.
+
+Contents of ``BASE_DIRS`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+Any relative paths are considered relative to the target's source directory. No
+two base directories for a file set may be sub-directories of each other. This
+requirement must be met across all base directories added to a file set.
diff --git a/Help/prop_fs/COMPILE_DEFINITIONS.rst b/Help/prop_fs/COMPILE_DEFINITIONS.rst
new file mode 100644
index 0000000..bc400bf
--- /dev/null
+++ b/Help/prop_fs/COMPILE_DEFINITIONS.rst
@@ -0,0 +1,37 @@
+COMPILE_DEFINITIONS
+-------------------
+
+.. versionadded:: 4.4
+
+Preprocessor definitions for compiling a source file.
+
+The ``COMPILE_DEFINITIONS`` property may be set to a semicolon-separated
+list of preprocessor definitions using the syntax ``VAR`` or ``VAR=value``.
+Function-style definitions are not supported. CMake will
+automatically escape the value correctly for the native build system
+(note that CMake language syntax may require escapes to specify some
+values).
+
+CMake will automatically drop some definitions that are not supported
+by the native build tool. :generator:`Xcode` does not support
+per-configuration definitions on source files.
+
+.. include:: /include/COMPILE_DEFINITIONS_DISCLAIMER.rst
+
+Contents of ``COMPILE_DEFINITIONS`` may use :manual:`cmake-generator-expressions(7)`
+with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. However, :generator:`Xcode`
+does not support per-config per-source settings, so expressions
+that depend on the build configuration are not allowed with that
+generator.
+
+Related properties:
+
+* Use :prop_fs:`COMPILE_OPTIONS` to pass additional compile flags.
+* Use :prop_fs:`INCLUDE_DIRECTORIES` to pass additional include directories.
+
+Related commands:
+
+* :command:`add_compile_definitions` for directory-wide settings
+* :command:`target_compile_definitions` for target-specific settings
+* :command:`set_source_files_properties` for source-specific settings
diff --git a/Help/prop_fs/COMPILE_OPTIONS.rst b/Help/prop_fs/COMPILE_OPTIONS.rst
new file mode 100644
index 0000000..70614b1
--- /dev/null
+++ b/Help/prop_fs/COMPILE_OPTIONS.rst
@@ -0,0 +1,36 @@
+COMPILE_OPTIONS
+---------------
+
+.. versionadded:: 4.4
+
+List of additional options to pass to the compiler.
+
+This property holds a :ref:`semicolon-separated list <CMake Language Lists>`
+of options and will be added to the list of compile flags when the sources of
+this file set are built. The options will be added after target-wide options
+and source level ones.
+
+Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the
+syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
+for available expressions. However, :generator:`Xcode`
+does not support per-config per-source settings, so expressions
+that depend on the build configuration are not allowed with that
+generator.
+
+Usage example:
+
+.. code-block:: cmake
+
+ set_property(FILE_SET SOURCES TARGET foo PROPERTY
+ COMPILE_OPTIONS "-Wno-unused-parameter;-Wno-missing-field-initializer")
+
+Related properties:
+
+* Use :prop_fs:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions.
+* Use :prop_fs:`INCLUDE_DIRECTORIES` to pass additional include directories.
+
+Related commands:
+
+* :command:`add_compile_options` for directory-wide settings
+* :command:`target_compile_options` for target-specific settings
+* :command:`set_source_files_properties` for source-specific settings
diff --git a/Help/prop_fs/CXX_SCAN_FOR_MODULES.rst b/Help/prop_fs/CXX_SCAN_FOR_MODULES.rst
new file mode 100644
index 0000000..f4c92a0
--- /dev/null
+++ b/Help/prop_fs/CXX_SCAN_FOR_MODULES.rst
@@ -0,0 +1,20 @@
+CXX_SCAN_FOR_MODULES
+--------------------
+
+.. versionadded:: 4.4
+
+``CXX_SCAN_FOR_MODULES`` is a boolean specifying whether CMake will scan the
+file set's sources for C++ module dependencies. See also the
+:prop_sf:`CXX_SCAN_FOR_MODULES` source file property and the
+:prop_tgt:`CXX_SCAN_FOR_MODULES` target property settings.
+
+When this property is set ``ON``, CMake will scan the file set's sources at
+build time and add module dependency information to the compile line as
+necessary. When this property is set ``OFF``, CMake will not scan the sources
+at build time. When this property is unset, the
+:prop_sf:`CXX_SCAN_FOR_MODULES` source file property and
+:prop_tgt:`CXX_SCAN_FOR_MODULES` target property are consulted, in that order.
+
+Note that scanning is only performed if C++20 or higher is enabled for the
+target and the source uses the ``CXX`` language. Scanning for modules in
+sources belonging to file sets of type ``CXX_MODULES`` is always performed.
diff --git a/Help/prop_fs/INCLUDE_DIRECTORIES.rst b/Help/prop_fs/INCLUDE_DIRECTORIES.rst
new file mode 100644
index 0000000..fd940ec
--- /dev/null
+++ b/Help/prop_fs/INCLUDE_DIRECTORIES.rst
@@ -0,0 +1,31 @@
+INCLUDE_DIRECTORIES
+-------------------
+
+.. versionadded:: 4.4
+
+List of preprocessor include file search directories.
+
+This property holds a :ref:`semicolon-separated list <CMake Language Lists>` of paths
+and will be added to the list of include directories when the sources of this
+file set are built. These directories will take precedence over directories
+defined at target level and source level except for :generator:`Xcode`
+generator due to technical limitations.
+
+Relative paths should not be added to this property directly.
+
+Contents of ``INCLUDE_DIRECTORIES`` may use "generator expressions" with
+the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
+for available expressions. However, :generator:`Xcode` does not support
+per-config per-source settings, so expressions that depend on the build
+configuration are not allowed with that generator.
+
+Related properties:
+
+* Use :prop_fs:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions.
+* Use :prop_fs:`COMPILE_OPTIONS` to pass additional compile flags.
+
+Related commands:
+
+* :command:`include_directories` for directory-wide settings
+* :command:`target_include_directories` for target-specific settings
+* :command:`set_source_files_properties` for source-specific settings
diff --git a/Help/prop_fs/INDEPENDENT_FILES.rst b/Help/prop_fs/INDEPENDENT_FILES.rst
new file mode 100644
index 0000000..8536276
--- /dev/null
+++ b/Help/prop_fs/INDEPENDENT_FILES.rst
@@ -0,0 +1,33 @@
+INDEPENDENT_FILES
+-----------------
+
+.. versionadded:: 4.4
+
+``INDEPENDENT_FILES`` is a boolean specifying that any :prop_sf:`GENERATED`
+sources in the file set are not necessary for the compilation of other sources
+in the same target. Stated another way, these files are "independent" and their
+presence is never necessary for compilation of other sources (e.g., via
+``#include``).
+
+When this property is ``ON``, :ref:`Ninja Generators` will omit conservative
+order-only dependencies that prevent a target's source files from compiling
+before custom commands from the target's dependencies are finished, even if
+those custom commands only produce sources independent from other sources in
+the same target.
+When this property is ``OFF``, :ref:`Ninja Generators` will apply conservative
+order-only dependencies that prevent a target's source files from compiling
+before custom commands from the target's dependencies are finished, even if
+those custom commands only produce sources independent from other sources in
+the same target.
+
+If this property is not defined, the following default will be applied:
+* ``ON`` for ``CXX_MODULES`` file set type.
+* ``OFF`` for all other file set types.
+
+In the case of the ``CXX_MODULES`` file set type, the only supported mode is
+``ON``. So if the property is set to ``OFF``, it will be ignored.
+
+In the case of the ``HEADERS`` file set type, if the property is ``ON``, an
+author warning will be emit because this mode is not supported.
+
+This property is effective only when the policy :policy:`CMP0154` is ``NEW``.
diff --git a/Help/prop_fs/INTERFACE_COMPILE_DEFINITIONS.rst b/Help/prop_fs/INTERFACE_COMPILE_DEFINITIONS.rst
new file mode 100644
index 0000000..5c102ee
--- /dev/null
+++ b/Help/prop_fs/INTERFACE_COMPILE_DEFINITIONS.rst
@@ -0,0 +1,15 @@
+INTERFACE_COMPILE_DEFINITIONS
+-----------------------------
+
+.. versionadded:: 4.4
+
+.. |property_name| replace:: compile definitions
+.. |command_name| replace:: :command:`set_property(FILE_SET)`
+.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_COMPILE_DEFINITIONS``
+.. include:: include/INTERFACE_BUILD_PROPERTY.rst
+
+Related properties:
+
+* Use :prop_fs:`INTERFACE_COMPILE_OPTIONS` to pass additional compile flags.
+* Use :prop_fs:`INTERFACE_INCLUDE_DIRECTORIES` to pass additional include
+ directories.
diff --git a/Help/prop_fs/INTERFACE_COMPILE_OPTIONS.rst b/Help/prop_fs/INTERFACE_COMPILE_OPTIONS.rst
new file mode 100644
index 0000000..cd30776
--- /dev/null
+++ b/Help/prop_fs/INTERFACE_COMPILE_OPTIONS.rst
@@ -0,0 +1,16 @@
+INTERFACE_COMPILE_OPTIONS
+-------------------------
+
+.. versionadded:: 4.4
+
+.. |property_name| replace:: compile options
+.. |command_name| replace:: :command:`set_property(FILE_SET)`
+.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_COMPILE_OPTIONS``
+.. include:: include/INTERFACE_BUILD_PROPERTY.rst
+
+Related properties:
+
+* Use :prop_fs:`INTERFACE_COMPILE_DEFINITIONS` to pass additional preprocessor
+ definitions.
+* Use :prop_fs:`INTERFACE_INCLUDE_DIRECTORIES` to pass additional include
+ directories.
diff --git a/Help/prop_fs/INTERFACE_INCLUDE_DIRECTORIES.rst b/Help/prop_fs/INTERFACE_INCLUDE_DIRECTORIES.rst
new file mode 100644
index 0000000..880a234
--- /dev/null
+++ b/Help/prop_fs/INTERFACE_INCLUDE_DIRECTORIES.rst
@@ -0,0 +1,35 @@
+INTERFACE_INCLUDE_DIRECTORIES
+-----------------------------
+
+.. versionadded:: 4.4
+
+.. |property_name| replace:: include directories
+.. |command_name| replace:: :command:`set_property(FILE_SET)`
+.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_INCLUDE_DIRECTORIES``
+.. include:: include/INTERFACE_BUILD_PROPERTY.rst
+
+Include directories usage requirements commonly differ between the build-tree
+and the install-tree. The ``BUILD_INTERFACE`` and ``INSTALL_INTERFACE``
+generator expressions can be used to describe separate usage requirements
+based on the usage location. Relative paths are allowed within the
+``INSTALL_INTERFACE`` expression and are interpreted relative to the
+installation prefix. For example:
+
+.. code-block:: cmake
+
+ set_property(FILE_SET myfile_set TARGET mylib PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib>
+ $<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib
+ )
+
+Related properties:
+
+* Use :prop_fs:`INTERFACE_COMPILE_DEFINITIONS` to pass additional preprocessor
+ definitions.
+* Use :prop_fs:`INTERFACE_COMPILE_OPTIONS` to pass additional compile flags.
+
+Creating Relocatable Packages
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. |INTERFACE_PROPERTY_LINK| replace:: ``INTERFACE_INCLUDE_DIRECTORIES``
+.. include:: /include/INTERFACE_INCLUDE_DIRECTORIES_WARNING.rst
diff --git a/Help/prop_fs/INTERFACE_SOURCES.rst b/Help/prop_fs/INTERFACE_SOURCES.rst
new file mode 100644
index 0000000..ca9e1c1
--- /dev/null
+++ b/Help/prop_fs/INTERFACE_SOURCES.rst
@@ -0,0 +1,34 @@
+INTERFACE_SOURCES
+-----------------
+
+.. versionadded:: 4.4
+
+List of interface sources to compile into consuming targets.
+The :command:`target_sources` command sets or adds to the ``INTERFACE_SOURCES``
+file set property for the file sets defined with the ``PUBLIC`` or
+``INTERFACE`` keyword and is the usual way to manipulate it.
+
+Contents of ``INTERFACE_SOURCES`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+Each file must be in one of the base directories, or a subdirectory of one of
+the base directories.
+
+If relative paths are specified, they are considered relative to the target's
+source directory.
+
+The following behavior applies for the :prop_fs:`SOURCES` and
+``INTERFACE_SOURCES`` file set properties, dependent on the value of the
+:prop_fs:`SCOPE` file set property:
+
+``PRIVATE``
+ Only the :prop_fs:`SOURCES` property can be set. Any change to the
+ ``INTERFACE_SOURCES`` property will be ignored.
+
+``PUBLIC``
+ :prop_fs:`SOURCES` and ``INTERFACE_SOURCES`` properties will always have the
+ same content.
+
+``INTERFACE``
+ Only the ``INTERFACE_SOURCES`` property can be set. Any change to the
+ :prop_fs:`SOURCES` property will be ignored.
diff --git a/Help/prop_fs/SCOPE.rst b/Help/prop_fs/SCOPE.rst
new file mode 100644
index 0000000..e326e2e
--- /dev/null
+++ b/Help/prop_fs/SCOPE.rst
@@ -0,0 +1,10 @@
+SCOPE
+-----
+
+.. versionadded:: 4.4
+
+The scope of the file set.
+
+This read-only property can be used to retrieve the
+:ref:`scope <Target Command Scope>` of the given file set.
+It will be ``PRIVATE``, ``PUBLIC``, or ``INTERFACE``.
diff --git a/Help/prop_fs/SOURCES.rst b/Help/prop_fs/SOURCES.rst
new file mode 100644
index 0000000..da97c59
--- /dev/null
+++ b/Help/prop_fs/SOURCES.rst
@@ -0,0 +1,32 @@
+SOURCES
+-------
+
+.. versionadded:: 4.4
+
+This specifies the list of paths to sources for the file set.
+The :command:`target_sources` command sets or adds to the ``SOURCES`` file set
+property for the file sets defined with the ``PRIVATE`` or ``PUBLIC`` keyword
+and is the usual way to manipulate it.
+
+Contents of ``SOURCES`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+Each file must be in one of the base directories, or a subdirectory of one of
+the base directories. If relative paths are specified, they are considered
+relative to the target's source directory.
+
+The following behavior applies for the ``SOURCES`` and
+:prop_fs:`INTERFACE_SOURCES` file set properties, dependent on the value of the
+:prop_fs:`SCOPE` file set property:
+
+``PRIVATE``
+ Only the ``SOURCES`` property can be set. Any change to
+ the :prop_fs:`INTERFACE_SOURCES` property will be ignored.
+
+``PUBLIC``
+ ``SOURCES`` and :prop_fs:`INTERFACE_SOURCES` properties will always have the
+ same content.
+
+``INTERFACE``
+ Only the :prop_fs:`INTERFACE_SOURCES` property can be set. Any change to
+ ``SOURCES`` property will be ignored.
diff --git a/Help/prop_fs/TYPE.rst b/Help/prop_fs/TYPE.rst
new file mode 100644
index 0000000..83a1005
--- /dev/null
+++ b/Help/prop_fs/TYPE.rst
@@ -0,0 +1,10 @@
+TYPE
+----
+
+.. versionadded:: 4.4
+
+The type of the file set.
+
+This read-only property can be used to retrieve the
+:ref:`type <File Sets>` of the given file set.
+Possible values are ``CXX_MODULES``, ``SOURCES``, or ``HEADERS``.
diff --git a/Help/prop_fs/include/INTERFACE_BUILD_PROPERTY.rst b/Help/prop_fs/include/INTERFACE_BUILD_PROPERTY.rst
new file mode 100644
index 0000000..dba863c
--- /dev/null
+++ b/Help/prop_fs/include/INTERFACE_BUILD_PROPERTY.rst
@@ -0,0 +1,16 @@
+List of public |property_name| requirements for a file set.
+
+File sets may populate this property to publish the |property_name|
+required to compile the sources for the target. The |command_name|
+command populates this property.
+
+When target dependencies are specified using :command:`target_link_libraries`,
+CMake will read this property from file sets of all target dependencies to
+determine the build properties of the consumer. These build properties are only
+applied to the sources of the file sets. The other sources of the consumer are
+unaffected.
+
+Contents of |PROPERTY_INTERFACE_NAME| may use "generator expressions"
+with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+-manual for more on defining buildsystem properties.
diff --git a/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst b/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst
index d10969a..318a8e2 100644
--- a/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst
+++ b/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst
@@ -5,12 +5,14 @@
``CXX_SCAN_FOR_MODULES`` is a boolean specifying whether CMake will scan the
source for C++ module dependencies. See also the
-:prop_tgt:`CXX_SCAN_FOR_MODULES` for target-wide settings.
+:prop_fs:`CXX_SCAN_FOR_MODULES` file set property which, if set,
+overrides the per-source settings and the
+:prop_tgt:`CXX_SCAN_FOR_MODULES` target property.
When this property is set ``ON``, CMake will scan the source at build time and
add module dependency information to the compile line as necessary. When this
property is set ``OFF``, CMake will not scan the source at build time. When
-this property is unset, the :prop_tgt:`CXX_SCAN_FOR_MODULES` property is
+this property is unset, the :prop_tgt:`CXX_SCAN_FOR_MODULES` target property is
consulted.
Note that scanning is only performed if C++20 or higher is enabled for the
diff --git a/Help/prop_sf/HEADER_FILE_ONLY.rst b/Help/prop_sf/HEADER_FILE_ONLY.rst
index 71d62ae..4575fab 100644
--- a/Help/prop_sf/HEADER_FILE_ONLY.rst
+++ b/Help/prop_sf/HEADER_FILE_ONLY.rst
@@ -4,7 +4,7 @@
Is this source file only a header file.
A property on a source file that indicates if the source file is a
-header file with no associated implementation. This is set
+header file that should not be compiled into an object file. This is set
automatically based on the file extension and is used by CMake to
determine if certain dependency information should be computed.
diff --git a/Help/prop_sf/Rust_EMIT.rst b/Help/prop_sf/Rust_EMIT.rst
new file mode 100644
index 0000000..548a485
--- /dev/null
+++ b/Help/prop_sf/Rust_EMIT.rst
@@ -0,0 +1,39 @@
+Rust_EMIT
+---------
+
+.. versionadded:: 4.4
+
+.. note::
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
+
+This property controls the type of output generated by the Rust compiler. Can
+be one of several values:
+
+``link``
+ This is the default if the property is not set. The crate will be compiled
+ into an `rlib` file, e.g.: ``libfile.rs.rlib``
+
+ .. note::
+ CMake will automatically prefix the generated ``rlib`` file
+ with ``lib`` as the Rust compiler always requires such a
+ prefix for external crates.
+
+``obj``
+ Generate a native object file, e.g.: ``file.rs.o``
+
+``asm``
+ Generate an assembly file, e.g.: ``file.rs.s``
+
+.. note::
+ The ``obj`` and ``asm`` output types are known to have the following
+ limitations:
+
+ * When enabled, the Rust compiler disables multiple codegen units and
+ ThinLTO. Depending on the situation, this can affect the generated code,
+ optimizations. It also reduce the internal parallelism inside and the
+ compiler and can reduce the effectiveness of incremental rebuilds.
+ * The generated ``obj`` files cannot be used as external crates, so other
+ Rust code can only use C-style API from them.
+ * The generated ``obj`` files cannot be linked as-is with native linkers,
+ additional crates from the Rust toolchain needs to linked too. The actual
+ crates to link depend on the code and compiler options.
diff --git a/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst b/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst
index 791914e..d61846d 100644
--- a/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst
+++ b/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst
@@ -5,7 +5,8 @@
``CXX_SCAN_FOR_MODULES`` is a boolean specifying whether CMake will scan C++
sources in the target for module dependencies. See also the
-:prop_sf:`CXX_SCAN_FOR_MODULES` for per-source settings which, if set,
+:prop_sf:`CXX_SCAN_FOR_MODULES` for per-source settings and
+:prop_fs:`CXX_SCAN_FOR_MODULES` for file set settings. If either is set, it
overrides the target-wide settings.
This property is initialized by the value of the
diff --git a/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst b/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst
new file mode 100644
index 0000000..4aba928
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst
@@ -0,0 +1,14 @@
+INTERFACE_SOURCE_SETS
+---------------------
+
+.. versionadded:: 4.4
+
+Read-only list of the target's ``INTERFACE`` and ``PUBLIC`` source sets (i.e.
+all file sets with the type ``SOURCES``). Files listed in these source sets
+can be installed with :command:`install(TARGETS)` and exported with
+:command:`install(EXPORT)` and :command:`export`.
+
+Source sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``SOURCES``.
+
+See also :prop_tgt:`SOURCE_SETS`.
diff --git a/Help/prop_tgt/Rust_EDITION.rst b/Help/prop_tgt/Rust_EDITION.rst
new file mode 100644
index 0000000..454b1b1
--- /dev/null
+++ b/Help/prop_tgt/Rust_EDITION.rst
@@ -0,0 +1,25 @@
+Rust_EDITION
+------------
+
+.. versionadded:: 4.4
+
+.. note::
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
+
+The Rust edition required to build this target. It is initialized from the
+:variable:`CMAKE_Rust_EDITION` variable if defined. Setting this property
+results in adding a flag such as ``--edition=2018`` to the compile line.
+
+Supported values are:
+
+``2015``
+ Rust 2015, the default edition, started with Rust 1.0.
+
+``2018``
+ Rust 2018, available since Rust 1.31.
+
+``2021``
+ Rust 2021, available since Rust 1.56.
+
+``2024``
+ Rust 2024, available since Rust 1.85.
diff --git a/Help/prop_tgt/SOURCE_DIRS.rst b/Help/prop_tgt/SOURCE_DIRS.rst
new file mode 100644
index 0000000..4442aa5
--- /dev/null
+++ b/Help/prop_tgt/SOURCE_DIRS.rst
@@ -0,0 +1,14 @@
+SOURCE_DIRS
+-----------
+
+.. versionadded:: 4.4
+
+Semicolon-separated list of base directories of the target's default
+source set (i.e. the file set with name and type ``SOURCES``). The property
+supports :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`SOURCE_DIRS_<NAME>` for the list of base directories in
+other source sets.
diff --git a/Help/prop_tgt/SOURCE_DIRS_NAME.rst b/Help/prop_tgt/SOURCE_DIRS_NAME.rst
new file mode 100644
index 0000000..22f198f
--- /dev/null
+++ b/Help/prop_tgt/SOURCE_DIRS_NAME.rst
@@ -0,0 +1,15 @@
+SOURCE_DIRS_<NAME>
+------------------
+
+.. versionadded:: 4.4
+
+Semicolon-separated list of base directories of the target's ``<NAME>``
+source set, which has the set type ``SOURCES``. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`SOURCE_DIRS` for the list of base directories in the
+default source set. See :prop_tgt:`SOURCE_SETS` for the file set names of all
+source sets.
diff --git a/Help/prop_tgt/SOURCE_SET.rst b/Help/prop_tgt/SOURCE_SET.rst
new file mode 100644
index 0000000..c7f517e
--- /dev/null
+++ b/Help/prop_tgt/SOURCE_SET.rst
@@ -0,0 +1,15 @@
+SOURCE_SET
+----------
+
+.. versionadded:: 4.4
+
+Semicolon-separated list of files in the target's default source set,
+(i.e. the file set with name and type ``SOURCES``). If any of the paths
+are relative, they are computed relative to the target's source directory.
+The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`SOURCE_SET_<NAME>` for the list of files in other source sets.
diff --git a/Help/prop_tgt/SOURCE_SETS.rst b/Help/prop_tgt/SOURCE_SETS.rst
new file mode 100644
index 0000000..b6fad22
--- /dev/null
+++ b/Help/prop_tgt/SOURCE_SETS.rst
@@ -0,0 +1,14 @@
+SOURCE_SETS
+-----------
+
+.. versionadded:: 4.4
+
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` source sets (i.e.
+all file sets with the type ``SOURCES``). Files listed in these file sets are
+treated as source files.
+
+Source sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``SOURCES``.
+
+See also :prop_tgt:`SOURCE_SET_<NAME>`, :prop_tgt:`SOURCE_SET` and
+:prop_tgt:`INTERFACE_SOURCE_SETS`.
diff --git a/Help/prop_tgt/SOURCE_SET_NAME.rst b/Help/prop_tgt/SOURCE_SET_NAME.rst
new file mode 100644
index 0000000..9eef526
--- /dev/null
+++ b/Help/prop_tgt/SOURCE_SET_NAME.rst
@@ -0,0 +1,15 @@
+SOURCE_SET_<NAME>
+-----------------
+
+.. versionadded:: 4.4
+
+Semicolon-separated list of files in the target's ``<NAME>`` source set,
+which has the set type ``SOURCES``. If any of the paths are relative,
+they are computed relative to the target's source directory. The property
+supports :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`SOURCE_SET` for the list of files in the default source set.
+See :prop_tgt:`SOURCE_SETS` for the file set names of all source sets.
diff --git a/Help/prop_tgt/VERIFY_INTERFACE_HEADER_SETS.rst b/Help/prop_tgt/VERIFY_INTERFACE_HEADER_SETS.rst
index a14f7c8..59cd104 100644
--- a/Help/prop_tgt/VERIFY_INTERFACE_HEADER_SETS.rst
+++ b/Help/prop_tgt/VERIFY_INTERFACE_HEADER_SETS.rst
@@ -3,16 +3,27 @@
.. versionadded:: 3.24
+.. versionchanged:: 4.4
+ ``OBJC`` and ``OBJCXX`` languages are now supported in addition to ``C``
+ and ``CXX``.
+
Used to verify that all headers in a target's ``PUBLIC`` and ``INTERFACE``
header sets can be included on their own.
+.. versionchanged:: 4.4
+ Previously, the verification target was only created when the target had
+ at least one matching header. Now it is always created when the property
+ is enabled.
+
When this property is set to true, and the target is an object library, static
library, shared library, interface library, or executable (subject to policy
-:policy:`CMP0209`) and the target has one or more ``PUBLIC`` or ``INTERFACE``
-header sets, an object library target named
+:policy:`CMP0209`), an object library target named
``<target_name>_verify_interface_header_sets`` is created. This verification
-target has one source file per header in the ``PUBLIC`` and ``INTERFACE``
-header sets. Each source file only includes its associated header file.
+target has one source file per header in the target's ``PUBLIC`` and
+``INTERFACE`` header sets. Each source file only includes its associated
+header file. If the target has no matching header sets, a utility target is
+created instead so that the target name always exists for build system
+dependencies.
The verification target links against the original target to get all of its
usage requirements.
diff --git a/Help/prop_tgt/VERIFY_PRIVATE_HEADER_SETS.rst b/Help/prop_tgt/VERIFY_PRIVATE_HEADER_SETS.rst
index df9d183..889a207 100644
--- a/Help/prop_tgt/VERIFY_PRIVATE_HEADER_SETS.rst
+++ b/Help/prop_tgt/VERIFY_PRIVATE_HEADER_SETS.rst
@@ -3,16 +3,26 @@
.. versionadded:: 4.3
+.. versionchanged:: 4.4
+ ``OBJC`` and ``OBJCXX`` languages are now supported in addition to ``C``
+ and ``CXX``.
+
Used to verify that all headers in a target's ``PUBLIC`` and ``PRIVATE``
header sets can be included on their own.
+.. versionchanged:: 4.4
+ Previously, the verification target was only created when the target had
+ at least one matching header. Now it is always created when the property
+ is enabled.
+
When this property is set to true, and the target is an object library, static
-library, shared library, module library, interface library, or executable, and
-the target has one or more ``PUBLIC`` or ``PRIVATE`` header sets, an object
-library target named ``<target_name>_verify_private_header_sets`` is created.
-This verification target has one source file per header in the ``PUBLIC`` and
-``PRIVATE`` header sets. Each source file only includes its associated header
-file.
+library, shared library, module library, interface library, or executable, an
+object library target named ``<target_name>_verify_private_header_sets`` is
+created. This verification target has one source file per header in the
+target's ``PUBLIC`` and ``PRIVATE`` header sets. Each source file only
+includes its associated header file. If the target has no matching header
+sets, a utility target is created instead so that the target name always
+exists for build system dependencies.
Properties affecting compilation are copied from the original target to the
verification target so that the headers will be interpreted the same way by
diff --git a/Help/prop_tgt/include/VERIFY_XXX_HEADER_SETS.rst b/Help/prop_tgt/include/VERIFY_XXX_HEADER_SETS.rst
index f190213..b8e8d07 100644
--- a/Help/prop_tgt/include/VERIFY_XXX_HEADER_SETS.rst
+++ b/Help/prop_tgt/include/VERIFY_XXX_HEADER_SETS.rst
@@ -6,11 +6,16 @@
If the header's :prop_sf:`LANGUAGE` property is set, the value of that property
is used to determine the language with which to compile the header file.
-Otherwise, if the target has any C++ sources, the header is compiled as C++.
-Otherwise, if the target has any C sources, the header is compiled as C.
-Otherwise, if C++ is enabled globally, the header is compiled as C++.
-Otherwise, if C is enabled globally, the header is compiled as C. Otherwise,
-the header file is not compiled.
+The supported languages are ``C``, ``CXX``, ``OBJC``, and ``OBJCXX``.
+If the language is not one of those four, the header file is not compiled.
+
+Otherwise, the language is inferred from the target's sources using the
+following precedence: ``OBJCXX`` takes priority over all others; if both
+``CXX`` and ``OBJC`` sources are present, the header is compiled as
+``OBJCXX``; otherwise ``CXX`` takes precedence over ``OBJC``, and ``OBJC``
+takes precedence over ``C``. If no matching sources are found, the same
+precedence is applied to the globally enabled languages. If no supported
+language is found, the header file is not compiled.
If the header's :prop_sf:`SKIP_LINTING` property is set to true, the file is
not compiled.
@@ -21,11 +26,10 @@
different, leading to the compiler interpreting the contents of the header
differently.
-If any |xxx| file set verification targets are created, a top-level target
-called |THIS_ALL_TARGET| is created which depends on all |xxx| verification
-targets. Another target called ``all_verify_header_sets`` is also created
-which depends on |THIS_ALL_TARGET|, and on |COMPLEMENTARY_ALL_TARGET| if it
-exists (see |COMPLEMENTARY_PROPERTY|).
+A top-level target called |THIS_ALL_TARGET| is created which depends on all
+|xxx| verification targets. Another target called ``all_verify_header_sets``
+is also created which depends on |THIS_ALL_TARGET|, and on
+|COMPLEMENTARY_ALL_TARGET| if it exists (see |COMPLEMENTARY_PROPERTY|).
This property is initialized by the value of the |INIT_VARIABLE| variable if
it is set when a target is created.
diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+ Developers should add similar notes for each topic branch
+ making a noteworthy change. Each document should be named
+ and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME-project-name-placeholder.rst b/Help/release/dev/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME-project-name-placeholder.rst
new file mode 100644
index 0000000..37dc626
--- /dev/null
+++ b/Help/release/dev/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME-project-name-placeholder.rst
@@ -0,0 +1,7 @@
+CMAKE_INSTALL_DEFAULT_COMPONENT_NAME-project-name-placeholder
+-------------------------------------------------------------
+
+* :variable:`CMAKE_INSTALL_DEFAULT_COMPONENT_NAME` gained support for a
+ special ``<PROJECT_NAME>`` placeholder value. It tells each
+ :command:`install` invocation to take a default component name
+ from the current :variable:`PROJECT_NAME` variable value.
diff --git a/Help/release/dev/CPACK_RPM_SPEC_MORE_DEFINE.rst b/Help/release/dev/CPACK_RPM_SPEC_MORE_DEFINE.rst
new file mode 100644
index 0000000..e2c4a0f
--- /dev/null
+++ b/Help/release/dev/CPACK_RPM_SPEC_MORE_DEFINE.rst
@@ -0,0 +1,4 @@
+CPACK_RPM_SPEC_MORE_DEFINE
+--------------------------
+
+* The :variable:`CPACK_RPM_SPEC_MORE_DEFINE` could be a list of definitions.
diff --git a/Help/release/dev/ExternalData-link-mode.rst b/Help/release/dev/ExternalData-link-mode.rst
new file mode 100644
index 0000000..f341e58
--- /dev/null
+++ b/Help/release/dev/ExternalData-link-mode.rst
@@ -0,0 +1,7 @@
+ExternalData-link-mode
+----------------------
+
+* The :module:`ExternalData` module gained an
+ :variable:`ExternalData_LINK_MODE` variable to select an ordered list
+ of file materialization modes for hard links, symbolic links, and
+ copies.
diff --git a/Help/release/dev/ExternalData-state-dir.rst b/Help/release/dev/ExternalData-state-dir.rst
new file mode 100644
index 0000000..df61d4d
--- /dev/null
+++ b/Help/release/dev/ExternalData-state-dir.rst
@@ -0,0 +1,6 @@
+ExternalData-state-dir
+----------------------
+
+* The :module:`ExternalData` module gained an
+ :variable:`ExternalData_STATE_ROOT` variable to store hash records outside
+ :variable:`ExternalData_BINARY_ROOT`.
diff --git a/Help/release/dev/ExternalProject-git-clone-retry.rst b/Help/release/dev/ExternalProject-git-clone-retry.rst
new file mode 100644
index 0000000..fafe1a6
--- /dev/null
+++ b/Help/release/dev/ExternalProject-git-clone-retry.rst
@@ -0,0 +1,7 @@
+ExternalProject-git-clone-retry
+-------------------------------
+
+* The :module:`ExternalProject` and :module:`FetchContent` modules gained
+ :variable:`CMAKE_EP_GIT_CLONE_RETRY_COUNT` and
+ :variable:`CMAKE_EP_GIT_CLONE_RETRY_DELAY` variables to control
+ ``git clone`` retries.
diff --git a/Help/release/dev/FILE_SET-CXX_SCAN_FOR_MODULES.rst b/Help/release/dev/FILE_SET-CXX_SCAN_FOR_MODULES.rst
new file mode 100644
index 0000000..8e963d4
--- /dev/null
+++ b/Help/release/dev/FILE_SET-CXX_SCAN_FOR_MODULES.rst
@@ -0,0 +1,5 @@
+FILE_SET-CXX_SCAN_FOR_MODULES
+-----------------------------
+
+* :ref:`File sets <file sets>` learned to support the
+ :prop_fs:`CXX_SCAN_FOR_MODULES` property.
diff --git a/Help/release/dev/FILE_SET-INDEPENDENT_FILES.rst b/Help/release/dev/FILE_SET-INDEPENDENT_FILES.rst
new file mode 100644
index 0000000..1274c68
--- /dev/null
+++ b/Help/release/dev/FILE_SET-INDEPENDENT_FILES.rst
@@ -0,0 +1,5 @@
+FILE_SET-INDEPENDENT_FILES
+--------------------------
+
+* :ref:`File sets <file sets>` learned to support the
+ :prop_fs:`INDEPENDENT_FILES` property.
diff --git a/Help/release/dev/FILE_SET-SOURCES.rst b/Help/release/dev/FILE_SET-SOURCES.rst
new file mode 100644
index 0000000..feb4902
--- /dev/null
+++ b/Help/release/dev/FILE_SET-SOURCES.rst
@@ -0,0 +1,4 @@
+FILE_SET-SOURCES
+----------------
+
+* The :ref:`file set <file sets>` gains the support of the ``SOURCES`` type.
diff --git a/Help/release/dev/FILE_SET-enforce-files-unicity.rst b/Help/release/dev/FILE_SET-enforce-files-unicity.rst
new file mode 100644
index 0000000..30e4ac4
--- /dev/null
+++ b/Help/release/dev/FILE_SET-enforce-files-unicity.rst
@@ -0,0 +1,5 @@
+FILE_SET-enforce-files-unicity
+------------------------------
+
+* A file may belong to at most one :ref:`file set <file sets>` in a target.
+ See policy :policy:`CMP0211`.
diff --git a/Help/release/dev/FILE_SET-new-properties.rst b/Help/release/dev/FILE_SET-new-properties.rst
new file mode 100644
index 0000000..764e2cc
--- /dev/null
+++ b/Help/release/dev/FILE_SET-new-properties.rst
@@ -0,0 +1,6 @@
+FILE_SET-new-properties
+-----------------------
+
+* File sets gained support for the :prop_fs:`SCOPE`, :prop_fs:`TYPE`,
+ :prop_fs:`BASE_DIRS`, :prop_fs:`SOURCES`, and
+ :prop_fs:`INTERFACE_SOURCES` file set properties.
diff --git a/Help/release/dev/add_custom_command-DEPENDS-exe.rst b/Help/release/dev/add_custom_command-DEPENDS-exe.rst
new file mode 100644
index 0000000..02bb71b
--- /dev/null
+++ b/Help/release/dev/add_custom_command-DEPENDS-exe.rst
@@ -0,0 +1,6 @@
+add_custom_command-DEPENDS-exe
+------------------------------
+
+* Names of executables given to the ``DEPENDS`` argument of
+ :command:`add_custom_command` no longer have ``.exe`` suffixes stripped to
+ establish target-level dependencies. See policy :policy:`CMP0212`.
diff --git a/Help/release/dev/always-create-all-verify-targets.rst b/Help/release/dev/always-create-all-verify-targets.rst
new file mode 100644
index 0000000..a634265
--- /dev/null
+++ b/Help/release/dev/always-create-all-verify-targets.rst
@@ -0,0 +1,9 @@
+always-create-all-verify-targets
+---------------------------------
+
+* The :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS` and
+ :prop_tgt:`VERIFY_PRIVATE_HEADER_SETS` target properties now always
+ create the per-target verification target and the aggregate
+ ``all_verify_interface_header_sets``, ``all_verify_private_header_sets``,
+ and ``all_verify_header_sets`` targets when the property is enabled,
+ even if the target has no matching header sets.
diff --git a/Help/release/dev/clang-cl-cxxmodules.rst b/Help/release/dev/clang-cl-cxxmodules.rst
new file mode 100644
index 0000000..7a3a23f
--- /dev/null
+++ b/Help/release/dev/clang-cl-cxxmodules.rst
@@ -0,0 +1,5 @@
+clang-cl-cxxmodules
+-------------------
+
+* C++ 20 named modules are now supported with ``clang-cl``.
+ See :manual:`cmake-cxxmodules(7)`.
diff --git a/Help/release/dev/cmake-E-copy-t-flag.rst b/Help/release/dev/cmake-E-copy-t-flag.rst
new file mode 100644
index 0000000..178292c
--- /dev/null
+++ b/Help/release/dev/cmake-E-copy-t-flag.rst
@@ -0,0 +1,10 @@
+cmake-E-copy-t-flag
+-------------------
+
+* The :option:`cmake -E` commands
+ :option:`copy_if_different <cmake-E copy_if_different>`,
+ :option:`copy_if_newer <cmake-E copy_if_newer>`,
+ :option:`copy_directory <cmake-E copy_directory>`,
+ :option:`copy_directory_if_different <cmake-E copy_directory_if_different>`,
+ and :option:`copy_directory_if_newer <cmake-E copy_directory_if_newer>`
+ gained support for the ``-t`` argument.
diff --git a/Help/release/dev/cmake-E-tar-encoding.rst b/Help/release/dev/cmake-E-tar-encoding.rst
new file mode 100644
index 0000000..30ac5f7
--- /dev/null
+++ b/Help/release/dev/cmake-E-tar-encoding.rst
@@ -0,0 +1,10 @@
+cmake-E-tar-encoding
+--------------------
+
+* The :option:`cmake -E tar <cmake-E tar>` command-line tool gained the
+ :option:`--cmake-tar-encoding <cmake-E_tar --cmake-tar-encoding>` flag
+ to specify the pathname encoding used in archives.
+
+* The :cpack_gen:`CPack Archive Generator` gained the
+ :variable:`CPACK_ARCHIVE_ENCODING` variable to specify the pathname
+ encoding used in package archives.
diff --git a/Help/release/dev/cmake-env-pch-disable.rst b/Help/release/dev/cmake-env-pch-disable.rst
new file mode 100644
index 0000000..9b74d7f
--- /dev/null
+++ b/Help/release/dev/cmake-env-pch-disable.rst
@@ -0,0 +1,5 @@
+cmake-env-pch-disable
+---------------------
+
+* The :envvar:`CMAKE_DISABLE_PRECOMPILE_HEADERS` environment variable
+ was added to disable precompiled headers by default.
diff --git a/Help/release/dev/cmake-install-j-no-space.rst b/Help/release/dev/cmake-install-j-no-space.rst
new file mode 100644
index 0000000..e3d3411
--- /dev/null
+++ b/Help/release/dev/cmake-install-j-no-space.rst
@@ -0,0 +1,5 @@
+cmake-install-j-no-space
+------------------------
+
+* :option:`cmake --install` now accepts ``-j<N>`` in addition to ``-j <N>``
+ for specifying the number of parallel jobs.
diff --git a/Help/release/dev/cmake-install-multi-component.rst b/Help/release/dev/cmake-install-multi-component.rst
new file mode 100644
index 0000000..0e3d3aa
--- /dev/null
+++ b/Help/release/dev/cmake-install-multi-component.rst
@@ -0,0 +1,5 @@
+cmake-install-multi-component
+-----------------------------
+
+* The :option:`cmake --install` command now supports installing
+ multiple components.
diff --git a/Help/release/dev/ctest-error-exit.rst b/Help/release/dev/ctest-error-exit.rst
new file mode 100644
index 0000000..1c1faad
--- /dev/null
+++ b/Help/release/dev/ctest-error-exit.rst
@@ -0,0 +1,5 @@
+ctest-error-exit
+----------------
+
+* :manual:`ctest(1)` now exits with non-zero if invoked with no
+ arguments and no test input file exists.
diff --git a/Help/release/dev/ctest-passthrough-args.rst b/Help/release/dev/ctest-passthrough-args.rst
new file mode 100644
index 0000000..93175e4
--- /dev/null
+++ b/Help/release/dev/ctest-passthrough-args.rst
@@ -0,0 +1,10 @@
+ctest-passthrough-args
+----------------------
+
+* :manual:`ctest(1)` gained support for forwarding extra arguments to test
+ executables using a :option:`-- <ctest -->` separator.
+
+* :manual:`cmake-presets(7)` gained support for a
+ ``testPassthroughArguments`` field in the
+ test preset ``execution`` object for
+ forwarding arguments to test executables via presets.
diff --git a/Help/release/dev/discover-tests.rst b/Help/release/dev/discover-tests.rst
new file mode 100644
index 0000000..8af674e
--- /dev/null
+++ b/Help/release/dev/discover-tests.rst
@@ -0,0 +1,11 @@
+discover-tests
+--------------
+
+* The :command:`discover_tests` command was added to support registering tests
+ discovered at test time by :manual:`ctest(1)`. It runs a user-provided
+ discovery command, parses its output, and generates test names, arguments,
+ and properties from regular-expression captures.
+
+* Test drivers generated by the :command:`create_test_sourcelist` command now
+ support the `-N` option to list all tests, one per line. This is useful in
+ combination with the new :command:`discover_tests` command.
diff --git a/Help/release/dev/execute_process-environment.rst b/Help/release/dev/execute_process-environment.rst
new file mode 100644
index 0000000..d14bc4b
--- /dev/null
+++ b/Help/release/dev/execute_process-environment.rst
@@ -0,0 +1,6 @@
+execute_process-environment
+---------------------------
+
+* The :command:`execute_process` command learned the
+ ``ENVIRONMENT`` and ``ENVIRONMENT_MODIFICATION`` options to run child
+ processes with a modified environment.
diff --git a/Help/release/dev/file-archive-encoding.rst b/Help/release/dev/file-archive-encoding.rst
new file mode 100644
index 0000000..3275c4c
--- /dev/null
+++ b/Help/release/dev/file-archive-encoding.rst
@@ -0,0 +1,7 @@
+file-archive-encoding
+---------------------
+
+* The :command:`file(ARCHIVE_CREATE)` and :command:`file(ARCHIVE_EXTRACT)`
+ commands accepts an ``ENCODING`` option to specify the encoding of the
+ archive pathnames. The default is now ``UTF-8``.
+ See policy :policy:`CMP0213`.
diff --git a/Help/release/dev/genex-TARGET_OBJECTS-SOURCE_FILES.rst b/Help/release/dev/genex-TARGET_OBJECTS-SOURCE_FILES.rst
new file mode 100644
index 0000000..623b9ad
--- /dev/null
+++ b/Help/release/dev/genex-TARGET_OBJECTS-SOURCE_FILES.rst
@@ -0,0 +1,7 @@
+genex-TARGET_OBJECTS-SOURCE_FILES
+---------------------------------
+
+* The :genex:`TARGET_OBJECTS` generator expression now has an optional
+ ``SOURCE_FILES:...`` argument, which can take one or more source files as
+ arguments, and will filter its output to only include objects built from
+ those source files.
diff --git a/Help/release/dev/googletest-listseparator.rst b/Help/release/dev/googletest-listseparator.rst
new file mode 100644
index 0000000..50a98ac
--- /dev/null
+++ b/Help/release/dev/googletest-listseparator.rst
@@ -0,0 +1,5 @@
+googletest-listseparator
+------------------------
+
+* The :module:`GoogleTest` module :command:`gtest_discover_tests` command
+ gained a ``LIST_SEPARATOR`` option.
diff --git a/Help/release/dev/nsis_ignore_components_page.rst b/Help/release/dev/nsis_ignore_components_page.rst
new file mode 100644
index 0000000..f5c36e3
--- /dev/null
+++ b/Help/release/dev/nsis_ignore_components_page.rst
@@ -0,0 +1,6 @@
+nsis_ignore_components_page
+---------------------------
+
+* The :cpack_gen:`CPack NSIS Generator` gained a new variable
+ :variable:`CPACK_NSIS_IGNORE_COMPONENTS_PAGE` to ignore the
+ component selection page in the installer.
diff --git a/Help/release/dev/presets-fileDir.rst b/Help/release/dev/presets-fileDir.rst
new file mode 100644
index 0000000..45f41d2
--- /dev/null
+++ b/Help/release/dev/presets-fileDir.rst
@@ -0,0 +1,7 @@
+presets-fileDir
+---------------
+
+* :manual:`cmake-presets(7)` files now support schema version 12. The
+ :ref:`${fileDir} <CMakePresets fileDir>` macro now always expands to the
+ directory of the preset file containing the ``${fileDir}`` macro, regardless
+ of whether it is inherited by another preset in a different directory.
diff --git a/Help/release/dev/verify-header-sets-objc.rst b/Help/release/dev/verify-header-sets-objc.rst
new file mode 100644
index 0000000..4b53e88
--- /dev/null
+++ b/Help/release/dev/verify-header-sets-objc.rst
@@ -0,0 +1,6 @@
+verify-header-sets-objc
+-----------------------
+
+* The :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS` and
+ :prop_tgt:`VERIFY_PRIVATE_HEADER_SETS` target properties now support
+ ``OBJC`` and ``OBJCXX`` languages in addition to ``C`` and ``CXX``.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index c525705..76550cb 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@
This file should include the adjacent "dev.txt" file
in development versions but not in release versions.
+.. include:: dev.txt
+
Releases
========
diff --git a/Help/variable/CMAKE_ERROR_DEPRECATED.rst b/Help/variable/CMAKE_ERROR_DEPRECATED.rst
index f3a6738..12aa50b 100644
--- a/Help/variable/CMAKE_ERROR_DEPRECATED.rst
+++ b/Help/variable/CMAKE_ERROR_DEPRECATED.rst
@@ -1,6 +1,8 @@
CMAKE_ERROR_DEPRECATED
----------------------
+.. deprecated:: 4.4
+
Whether to issue errors for deprecated functionality.
If ``TRUE``, use of deprecated functionality will issue fatal errors.
diff --git a/Help/variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME.rst b/Help/variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME.rst
index 57160f1..15ec0cd 100644
--- a/Help/variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME.rst
+++ b/Help/variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME.rst
@@ -7,3 +7,13 @@
these files will be grouped into a default component. The name of this
default install component will be taken from this variable. It
defaults to ``Unspecified``.
+
+There is a special component name:
+
+``<PROJECT_NAME>``
+ .. versionadded:: 4.4
+
+ This literal placeholder will expand to the contents of the
+ :variable:`PROJECT_NAME` variable when the :command:`install` command is
+ evaluated. If no :command:`project` command has been called it defaults to
+ ``Unspecified``.
diff --git a/Help/variable/CMAKE_INSTALL_PREFIX.rst b/Help/variable/CMAKE_INSTALL_PREFIX.rst
index 340bc35..f9fa96d 100644
--- a/Help/variable/CMAKE_INSTALL_PREFIX.rst
+++ b/Help/variable/CMAKE_INSTALL_PREFIX.rst
@@ -60,6 +60,5 @@
* The :option:`--install-prefix <cmake --install-prefix>` option.
* The :genex:`$<INSTALL_PREFIX>` generator expression.
-* The :ref:`installDir <CMakePresets installDir>` field in CMake configure
- presets.
+* The :preset:`configurePresets.installDir` field in CMake configure presets.
* The :variable:`CPACK_PACKAGING_INSTALL_PREFIX` variable.
diff --git a/Help/variable/CMAKE_Rust_EDITION.rst b/Help/variable/CMAKE_Rust_EDITION.rst
new file mode 100644
index 0000000..273aea6
--- /dev/null
+++ b/Help/variable/CMAKE_Rust_EDITION.rst
@@ -0,0 +1,10 @@
+CMAKE_Rust_EDITION
+------------------
+
+.. versionadded:: 4.4
+
+.. note::
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
+
+Default value for :prop_tgt:`Rust_EDITION` target property if set when a target
+is created.
diff --git a/Help/variable/CMAKE_SYSTEM_NAME.rst b/Help/variable/CMAKE_SYSTEM_NAME.rst
index de688b5..90b26ba 100644
--- a/Help/variable/CMAKE_SYSTEM_NAME.rst
+++ b/Help/variable/CMAKE_SYSTEM_NAME.rst
@@ -28,91 +28,270 @@
The following is a list of possible values, each associated with corresponding
operating systems or environments.
-========================= ======================================================
-Value Name
-========================= ======================================================
-``ADSP`` Analog Devices Audio Digital Signal Processing
-``AIX`` IBM Unix operating system
-``Android`` Android operating system
-``ARTOS`` Operating system for microcontrollers
-``BeOS`` Operating system for personal computers (discontinued)
-``BlueGeneL`` Blue Gene/L static environment
-``BlueGeneP-dynamic`` Blue Gene/P dynamic environment
-``BlueGeneP-static`` Blue Gene/P static environment
-``BlueGeneQ-dynamic`` Blue Gene/Q dynamic environment
-``BlueGeneQ-static`` Blue Gene/Q static environment
-``BSDOS`` BSD operating system (discontinued)
-``Catamount`` Operating system for Cray XT series
-``CrayLinuxEnvironment`` Cray Linux Environment
-``CYGWIN`` Cygwin environment for Windows
-``Darwin`` Apple stationary operating systems (macOS, OS X, etc.)
-``DOS`` MS-DOS or compatible
-``DragonFly`` BSD-derived operating system
-``eCos`` Real-time embedded operating system
-``Emscripten`` Compiler toolchain to WebAssembly
-``Euros`` Real-time operating system for embedded devices
-``FreeBSD`` FreeBSD operating system
-``Fuchsia`` Operating system by Google based on the Zircon kernel
-``Generic-ADSP`` Generic ADSP (Audio DSP) environment
-``Generic-ELF`` Generic ELF (Executable and Linkable Format) environment
-``Generic`` Some platforms, e.g. bare metal embedded devices
-``GHS-MULTI`` Green Hills Software MULTI environment
-``GNU`` GNU/Hurd-based operating system
-``Haiku`` Unix operating system inspired by BeOS
-``HP-UX`` Hewlett Packard Unix
-``iOS`` Apple mobile phone operating system
-``Linux`` All Linux-based distributions
-``Midipix`` POSIX-compatible layer for Windows
-``MirBSD`` MirOS BSD operating system
-``MP-RAS`` MP-RAS UNIX operating system
-``MSYS`` MSYS environment (MSYSTEM=MSYS)
-``NetBSD`` NetBSD operating systems
-``OpenBSD`` OpenBSD operating systems
-``OpenVMS`` OpenVMS operating system by HP
-``OS2`` OS/2 operating system
-``OSF1`` Compaq Tru64 UNIX (formerly DEC OSF/1, Digital Unix) (discontinued)
-``QNX`` Unix-like operating system by BlackBerry
-``RISCos`` RISC OS operating system
-``SCO_SV`` SCO OpenServer 5
-``SerenityOS`` Unix-like operating system
-``SINIX`` SINIX operating system
-``SunOS`` Oracle Solaris and all illumos operating systems
-``syllable`` Syllable operating system
-``Tru64`` Compaq Tru64 UNIX (formerly DEC OSF/1) operating system
-``tvOS`` Apple TV operating system
-``ULTRIX`` Unix operating system (discontinued)
-``UNIX_SV`` SCO UnixWare (pre release 7)
-``UnixWare`` SCO UnixWare 7
-``visionOS`` Apple mixed reality operating system
-``WASI`` WebAssembly System Interface
-``watchOS`` Apple watch operating system
-``Windows`` Windows stationary operating systems
-``WindowsCE`` Windows Embedded Compact
-``WindowsPhone`` Windows mobile phone operating system
-``WindowsStore`` Universal Windows Platform applications
-``Xenix`` SCO Xenix Unix operating system (discontinued)
-========================= ======================================================
+Apple Platforms
+"""""""""""""""
-Platform-specific notes:
+``Darwin``
+ Apple stationary operating systems (macOS, OS X, etc.)
-* MSYS2's ``msys/cmake`` package (``/usr/bin/cmake``) works only under
+``iOS``
+ .. versionadded:: 3.14
+
+ Apple mobile phone operating system
+
+``tvOS``
+ .. versionadded:: 3.14
+
+ Apple TV operating system
+
+``visionOS``
+ .. versionadded:: 3.28
+
+ Apple mixed reality operating system
+
+``watchOS``
+ .. versionadded:: 3.14
+
+ Apple watch operating system
+
+UNIX Platforms
+""""""""""""""
+
+``ADSP``
+ Analog Devices Audio Digital Signal Processing
+
+``AIX``
+ IBM Unix operating system
+
+``Android``
+ .. versionadded:: 3.1
+
+ Android operating system
+
+``ARTOS``
+ .. versionadded:: 3.4
+
+ Operating system for microcontrollers
+
+``BeOS``
+ Operating system for personal computers (discontinued)
+
+``BlueGeneL``
+ Blue Gene/L static environment
+
+``BlueGeneP-dynamic``
+ Blue Gene/P dynamic environment
+
+``BlueGeneP-static``
+ Blue Gene/P static environment
+
+``BlueGeneQ-dynamic``
+ .. versionadded:: 3.3
+
+ Blue Gene/Q dynamic environment
+
+``BlueGeneQ-static``
+ .. versionadded:: 3.3
+
+ Blue Gene/Q static environment
+
+``BSDOS``
+ BSD operating system (discontinued)
+
+``Catamount``
+ Operating system for Cray XT series
+
+``CrayLinuxEnvironment``
+ .. versionadded:: 3.5
+
+ Cray Linux Environment
+
+``DragonFly``
+ BSD-derived operating system
+
+``eCos``
+ Real-time embedded operating system
+
+``Emscripten``
+ .. versionadded:: 4.2
+
+ Compiler toolchain to WebAssembly.
+
+``Euros``
+ .. versionadded:: 3.4
+
+ Real-time operating system for embedded devices
+
+``FreeBSD``
+ FreeBSD operating system
+
+``Fuchsia``
+ .. versionadded:: 3.8
+
+ Operating system by Google based on the Zircon kernel
+
+``Generic-ADSP``
+ Generic ADSP (Audio DSP) environment
+
+``Generic-ELF``
+ .. versionadded:: 3.23
+
+ Generic ELF (Executable and Linkable Format) environment
+
+``Generic``
+ Some platforms, e.g. bare metal embedded devices
+
+``GHS-MULTI``
+ .. versionadded:: 3.3
+
+ Green Hills Software MULTI environment
+
+``GNU``
+ GNU/Hurd-based operating system
+
+``Haiku``
+ Unix operating system inspired by BeOS
+
+``HP-UX``
+ Hewlett Packard Unix (discontinued)
+
+``Linux``
+ All Linux-based distributions
+
+``MirBSD``
+ MirOS BSD operating system
+
+``MP-RAS``
+ MP-RAS UNIX operating system
+
+``NetBSD``
+ NetBSD operating systems
+
+``OHOS``
+ .. versionadded:: 3.30
+
+ OpenHarmony family of operating systems (e.g., HarmonyOS)
+
+ Toolchain file can set this value when targeting OpenHarmony operating
+ systems.
+
+``OpenBSD``
+ OpenBSD operating systems
+
+``OpenVMS``
+ OpenVMS operating system by HP
+
+``OS2``
+ .. versionadded:: 3.18
+
+ OS/2 operating system
+
+``OSF1``
+ Compaq Tru64 UNIX (formerly DEC OSF/1, Digital Unix) (discontinued)
+
+``QNX``
+ Unix-like operating system by BlackBerry
+
+``RISCos``
+ RISC OS operating system
+
+``SCO_SV``
+ SCO OpenServer 5
+
+``SerenityOS``
+ .. versionadded:: 3.25
+
+ Unix-like operating system
+
+``SINIX``
+ SINIX operating system
+
+``SunOS``
+ Oracle Solaris and all illumos operating systems
+
+``syllable``
+ Syllable operating system
+
+``Tru64``
+ Compaq Tru64 UNIX (formerly DEC OSF/1) operating system
+
+``ULTRIX``
+ Unix operating system (discontinued)
+
+``UNIX_SV``
+ SCO UnixWare (pre release 7)
+
+``UnixWare``
+ SCO UnixWare 7
+
+``WASI``
+ .. versionadded:: 3.31
+
+ WebAssembly System Interface
+
+``Xenix``
+ SCO Xenix Unix operating system (discontinued)
+
+Windows Platforms
+"""""""""""""""""
+
+``CYGWIN``
+ Cygwin environment for Windows
+
+ Cygwin's ``cmake`` package (``/usr/bin/cmake``) uses system name ``CYGWIN``.
+ A non-cygwin CMake on Windows (e.g. ``$PROGRAMFILES/CMake/bin/cmake``)
+ uses system name ``Windows`` even when it runs under a Cygwin environment.
+
+``DOS``
+ MS-DOS or compatible
+
+``Midipix``
+ .. versionadded:: 3.10
+
+ POSIX-compatible layer for Windows
+
+``MSYS``
+ MSYS environment (MSYSTEM=MSYS)
+
+ MSYS2's ``msys/cmake`` package (``/usr/bin/cmake``) works only under
``MSYSTEM=MSYS`` environments, with system name ``MSYS``. Under other
environments like ``MSYSTEM=MINGW64``, use another package such
as ``mingw64/mingw-w64-x86_64-cmake`` (``/mingw64/bin/cmake``),
which targets ``MSYSTEM=MINGW64`` with system name ``Windows``.
-* Cygwin's ``cmake`` package (``/usr/bin/cmake``) uses system name ``CYGWIN``.
- A non-cygwin CMake on Windows (e.g. ``$PROGRAMFILES/CMake/bin/cmake``)
- uses system name ``Windows`` even when it runs under a Cygwin environment.
+``Windows``
+ Windows stationary operating systems
+
+``WindowsCE``
+ Windows Embedded Compact
+
+``WindowsKernelModeDriver``
+ .. versionadded:: 4.1
+
+ Windows Kernel-Mode Driver
+
+ When building drivers for Kernel-Mode Driver Framework on Windows, toolchain
+ file can set this value. See also the :variable:`CMAKE_WINDOWS_KMDF_VERSION`
+ variable.
+
+``WindowsPhone``
+ .. versionadded:: 3.1
+
+ Windows mobile phone operating system
+
+``WindowsStore``
+ .. versionadded:: 3.1
+
+ Universal Windows Platform applications
Removed Platforms
-^^^^^^^^^^^^^^^^^
+"""""""""""""""""
The following platforms were once supported by CMake and got removed either due
to platform's EOL, or other incompatibilities:
-========================= ===================================== ================
-Value Name Removed in CMake
-========================= ===================================== ================
-``kFreeBSD`` FreeBSD kernel with a GNU userland 4.1
-========================= ===================================== ================
+``kFreeBSD``
+ .. versionchanged:: 4.1
+ Removed from CMake.
+
+ FreeBSD kernel with a GNU userland
diff --git a/Help/variable/CMAKE_WARN_DEPRECATED.rst b/Help/variable/CMAKE_WARN_DEPRECATED.rst
index c7b6159..ffe24bd 100644
--- a/Help/variable/CMAKE_WARN_DEPRECATED.rst
+++ b/Help/variable/CMAKE_WARN_DEPRECATED.rst
@@ -1,11 +1,13 @@
CMAKE_WARN_DEPRECATED
---------------------
+.. deprecated:: 4.4
+
Whether to issue warnings for deprecated functionality.
If not ``FALSE``, use of deprecated functionality will issue warnings.
If this variable is not set, CMake behaves as if it were set to ``TRUE``.
When running :manual:`cmake(1)`, this option can be enabled with the
-:option:`-Wdeprecated <cmake -Wdeprecated>` option, or disabled with the
-:option:`-Wno-deprecated <cmake -Wno-deprecated>` option.
+:option:`-Wdeprecated <cmake -W>` option, or disabled with the
+:option:`-Wno-deprecated <cmake -Wno->` option.
diff --git a/Help/variable/include/LINK_GROUP_PREDEFINED_FEATURES.rst b/Help/variable/include/LINK_GROUP_PREDEFINED_FEATURES.rst
index 557886e..f83fefd 100644
--- a/Help/variable/include/LINK_GROUP_PREDEFINED_FEATURES.rst
+++ b/Help/variable/include/LINK_GROUP_PREDEFINED_FEATURES.rst
@@ -20,3 +20,7 @@
This feature is available when using toolchains that target Linux, BSD, and
SunOS. It can also be used when targeting Windows platforms if the GNU
toolchain is used.
+
+ .. versionadded:: 4.4
+ ``RESCAN`` is additionally available when using toolchains targeting
+ Haiku.
diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in
index c79362e..65d3bab 100644
--- a/Modules/CMakeCCompilerId.c.in
+++ b/Modules/CMakeCCompilerId.c.in
@@ -44,16 +44,17 @@
#define C_STD_17 201710L
#define C_STD_23 202311L
-#ifdef __STDC_VERSION__
-# define C_STD __STDC_VERSION__
+#if defined(__STDC_VERSION__)
+# define C_STD __STDC_VERSION__
+#elif defined(__POCC_STDC_VERSION__)
+# define C_STD __POCC_STDC_VERSION__
+#elif defined(__STDC__) || defined(__clang__) || defined(_MSC_VER) || \
+ defined(__ibmxl__) || defined(__IBMC__) || defined(__RENESAS__)
+# define C_STD 1
#endif
-#if !defined(__STDC__) && !defined(__clang__) && !defined(__RENESAS__)
-# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__)
-# define C_VERSION "90"
-# else
-# define C_VERSION
-# endif
+#if !defined(C_STD)
+# define C_VERSION
#elif C_STD > C_STD_17
# define C_VERSION "23"
#elif C_STD > C_STD_11
diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in
index 4d78c2a..2e08785 100644
--- a/Modules/CMakeCXXCompilerId.cpp.in
+++ b/Modules/CMakeCXXCompilerId.cpp.in
@@ -63,7 +63,9 @@
# define CXX_STD __cplusplus
# endif
#elif defined(__NVCOMPILER)
-# if __cplusplus == CXX_STD_17 && defined(__cpp_aggregate_paren_init)
+# if __cplusplus > CXX_STD_20 && defined(__cpp_pp_embed)
+# define CXX_STD /*CXX_STD_26*/ (CXX_STD_23 + 1)
+# elif __cplusplus == CXX_STD_17 && defined(__cpp_aggregate_paren_init)
# define CXX_STD CXX_STD_20
# else
# define CXX_STD __cplusplus
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index 68182b8..a8e652c 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -74,6 +74,7 @@
list(APPEND ordered_compilers
TinyCC
Bruce
+ PellesC
)
endif()
list(APPEND ordered_compilers
diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake
index 097916e..8276da2 100644
--- a/Modules/CMakeDetermineCompiler.cmake
+++ b/Modules/CMakeDetermineCompiler.cmake
@@ -112,7 +112,7 @@
# if compiler (and arguments) comes from cache then synchronize cache with updated CMAKE_<LANG>_COMPILER
get_filename_component(_CMAKE_USER_${lang}_COMPILER_PATH "${CMAKE_${lang}_COMPILER}" PATH)
if(NOT _CMAKE_USER_${lang}_COMPILER_PATH)
- find_program(CMAKE_${lang}_COMPILER_WITH_PATH NAMES ${CMAKE_${lang}_COMPILER})
+ find_program(CMAKE_${lang}_COMPILER_WITH_PATH NO_CACHE NAMES ${CMAKE_${lang}_COMPILER})
if(CMAKE_${lang}_COMPILER_WITH_PATH)
set(CMAKE_${lang}_COMPILER ${CMAKE_${lang}_COMPILER_WITH_PATH})
get_property(_CMAKE_${lang}_COMPILER_CACHED CACHE CMAKE_${lang}_COMPILER PROPERTY TYPE)
@@ -121,7 +121,6 @@
endif()
unset(_CMAKE_${lang}_COMPILER_CACHED)
endif()
- unset(CMAKE_${lang}_COMPILER_WITH_PATH CACHE)
elseif (EXISTS ${CMAKE_${lang}_COMPILER})
get_property(_CMAKE_${lang}_COMPILER_CACHED CACHE CMAKE_${lang}_COMPILER PROPERTY TYPE)
if(_CMAKE_${lang}_COMPILER_CACHED)
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 0518128..118a202 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -465,7 +465,7 @@
#-----------------------------------------------------------------------------
# Function to write the compiler id source file.
function(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
- find_file(src_in ${src}.in PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
+ find_file(src_in ${src}.in NO_CACHE PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
file(READ ${src_in} ID_CONTENT_IN)
compiler_id_detection(CMAKE_${lang}_COMPILER_ID_CONTENT ${lang}
@@ -490,7 +490,6 @@
)
endif()
- unset(src_in CACHE)
string(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)
file(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}")
endfunction()
diff --git a/Modules/CMakeDetermineOBJCCompiler.cmake b/Modules/CMakeDetermineOBJCCompiler.cmake
index f8d334a..8aeadc1 100644
--- a/Modules/CMakeDetermineOBJCCompiler.cmake
+++ b/Modules/CMakeDetermineOBJCCompiler.cmake
@@ -76,11 +76,10 @@
# if the C compiler already had a path, reuse it for searching the CXX compiler
get_filename_component(_CMAKE_USER_OBJC_COMPILER_PATH "${CMAKE_OBJC_COMPILER}" PATH)
if(NOT _CMAKE_USER_OBJC_COMPILER_PATH)
- find_program(CMAKE_OBJC_COMPILER_WITH_PATH NAMES ${CMAKE_OBJC_COMPILER})
+ find_program(CMAKE_OBJC_COMPILER_WITH_PATH NO_CACHE NAMES ${CMAKE_OBJC_COMPILER})
if(CMAKE_OBJC_COMPILER_WITH_PATH)
set(CMAKE_OBJC_COMPILER ${CMAKE_OBJC_COMPILER_WITH_PATH} CACHE STRING "Objective-C compiler" FORCE)
endif()
- unset(CMAKE_OBJC_COMPILER_WITH_PATH CACHE)
endif()
endif()
mark_as_advanced(CMAKE_OBJC_COMPILER)
diff --git a/Modules/CMakeDetermineOBJCXXCompiler.cmake b/Modules/CMakeDetermineOBJCXXCompiler.cmake
index 0c03eea..b7df4e8 100644
--- a/Modules/CMakeDetermineOBJCXXCompiler.cmake
+++ b/Modules/CMakeDetermineOBJCXXCompiler.cmake
@@ -78,11 +78,10 @@
# if the C compiler already had a path, reuse it for searching the CXX compiler
get_filename_component(_CMAKE_USER_OBJCXX_COMPILER_PATH "${CMAKE_OBJCXX_COMPILER}" PATH)
if(NOT _CMAKE_USER_OBJCXX_COMPILER_PATH)
- find_program(CMAKE_OBJCXX_COMPILER_WITH_PATH NAMES ${CMAKE_OBJCXX_COMPILER})
+ find_program(CMAKE_OBJCXX_COMPILER_WITH_PATH NO_CACHE NAMES ${CMAKE_OBJCXX_COMPILER})
if(CMAKE_OBJCXX_COMPILER_WITH_PATH)
set(CMAKE_OBJCXX_COMPILER ${CMAKE_OBJCXX_COMPILER_WITH_PATH} CACHE STRING "Objective-C++ compiler" FORCE)
endif()
- unset(CMAKE_OBJCXX_COMPILER_WITH_PATH CACHE)
endif()
endif()
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 91543a6..3e77903 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -34,7 +34,7 @@
if(NOT _CMAKE_USER_TOOL_PATH)
# Find CMAKE_TOOL in the SEARCH_PATH directory by user-defined name.
- find_program(_CMAKE_TOOL_WITH_PATH NAMES ${${CMAKE_TOOL}} HINTS ${SEARCH_PATH} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH)
+ find_program(_CMAKE_TOOL_WITH_PATH NO_CACHE NAMES ${${CMAKE_TOOL}} HINTS ${SEARCH_PATH} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH)
if(_CMAKE_TOOL_WITH_PATH)
# Overwrite CMAKE_TOOL with full path found in SEARCH_PATH.
@@ -47,7 +47,6 @@
endif()
endif()
- unset(_CMAKE_TOOL_WITH_PATH CACHE)
endif()
@@ -108,6 +107,11 @@
set(_CMAKE_AR_NAMES "wlib")
list(APPEND _CMAKE_TOOL_VARS LINKER AR)
+elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xPellesC")
+ set(_CMAKE_LINKER_NAMES "polink")
+ set(_CMAKE_AR_NAMES "polib")
+ list(APPEND _CMAKE_TOOL_VARS LINKER AR)
+
elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$")
# Detect the `<lang>` compiler name
get_filename_component(__iar_selected_compiler "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" NAME)
diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in
index 3c8a82a..5292ea2 100644
--- a/Modules/CMakeOBJCCompilerId.m.in
+++ b/Modules/CMakeOBJCCompilerId.m.in
@@ -25,16 +25,14 @@
#define C_STD_17 201710L
#define C_STD_23 202311L
-#ifdef __STDC_VERSION__
+#if defined(__STDC_VERSION__)
# define C_STD __STDC_VERSION__
+#elif defined(__STDC__) || defined(__ibmxl__) || defined(__IBMC__)
+# define C_STD 1
#endif
-#if !defined(__STDC__)
-# if defined(__ibmxl__) || defined(__IBMC__)
-# define C_VERSION "90"
-# else
-# define C_VERSION
-# endif
+#if !defined(C_STD)
+# define C_VERSION
#elif C_STD > C_STD_17
# define C_VERSION "23"
#elif C_STD > C_STD_11
diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake
index 1b16a68..c69a710 100644
--- a/Modules/CMakeParseImplicitLinkInfo.cmake
+++ b/Modules/CMakeParseImplicitLinkInfo.cmake
@@ -119,7 +119,7 @@
if("${line}" MATCHES " --with-ld=([^ ]+/${linker})( |$)")
set(linker_tool_fallback "${CMAKE_MATCH_1}")
endif()
- elseif("${line}" MATCHES "vs_link.*-- +([^\"]*[/\\](${linker})) ") # cmake -E vs_link_exe
+ elseif("${line}" MATCHES "vs_link.*-- +\"?([^\"]*[/\\](${linker}))\"? ") # cmake -E vs_link_exe
set(linker_tool "${CMAKE_MATCH_1}")
elseif("${line}" MATCHES "${linker_tool_regex}")
set(linker_tool "${CMAKE_MATCH_2}")
diff --git a/Modules/CMakeRCInformation.cmake b/Modules/CMakeRCInformation.cmake
index cd991a0..b0a724f 100644
--- a/Modules/CMakeRCInformation.cmake
+++ b/Modules/CMakeRCInformation.cmake
@@ -39,7 +39,9 @@
# now define the following rule variables
# CMAKE_RC_COMPILE_OBJECT
-set(CMAKE_INCLUDE_FLAG_RC "-I ")
+if(NOT CMAKE_INCLUDE_FLAG_RC)
+ set(CMAKE_INCLUDE_FLAG_RC "-I ")
+endif()
# compile a Resource file into an object file
if(NOT CMAKE_RC_COMPILE_OBJECT)
set(CMAKE_RC_COMPILE_OBJECT
diff --git a/Modules/CMakeRustCompiler.cmake.in b/Modules/CMakeRustCompiler.cmake.in
index deb19ba..5da83e4 100644
--- a/Modules/CMakeRustCompiler.cmake.in
+++ b/Modules/CMakeRustCompiler.cmake.in
@@ -3,3 +3,8 @@
set(CMAKE_Rust_SOURCE_FILE_EXTENSIONS rs)
set(CMAKE_Rust_COMPILER_LOADED 1)
set(CMAKE_Rust_COMPILER_WORKS @CMAKE_Rust_COMPILER_WORKS@)
+
+# Make sure CMake prefers to link with Rust when Rust source files are present
+set(CMAKE_Rust_LINKER_PREFERENCE 60)
+# Once compiled by Rust, static libraries can be linked by anyone.
+set(CMAKE_Rust_LINKER_PREFERENCE_PROPAGATES 0)
diff --git a/Modules/CMakeRustInformation.cmake b/Modules/CMakeRustInformation.cmake
index 2224d01..e7d41fd 100644
--- a/Modules/CMakeRustInformation.cmake
+++ b/Modules/CMakeRustInformation.cmake
@@ -3,11 +3,20 @@
include(CMakeLanguageInformation)
-if(UNIX)
- set(CMAKE_Rust_OUTPUT_EXTENSION .o)
-else()
- set(CMAKE_Rust_OUTPUT_EXTENSION .obj)
-endif()
+set(CMAKE_Rust_OUTPUT_EXTENSION .rlib)
+
+# Other values are supported to generate various outputs (LLVM bitcode, or IR,
+# crate metadata, Rust MIR). However, CMake cannot do anything with those
+# outputs, so we list output which can be reused in later stages of the build.
+# See: https://doc.rust-lang.org/rustc/command-line-arguments.html#--emit-specifies-the-types-of-output-files-to-generate
+set(CMAKE_Rust_EMIT_VALUES link obj asm)
+
+# The output extension for each supported emit value.
+set(CMAKE_Rust_EMIT_link_OUTPUT_EXTENSION .rlib)
+set(CMAKE_Rust_EMIT_asm_OUTPUT_EXTENSION .s)
+# Might be switched to .obj on Windows when using MSVC target triple, see:
+# https://github.com/rust-lang/rust/issues/37207
+set(CMAKE_Rust_EMIT_obj_OUTPUT_EXTENSION .o)
set(CMAKE_Rust_LIBRARY_PATH_FLAG "-L ")
set(CMAKE_Rust_LINK_LIBRARY_FILE_FLAG "-C link-arg=")
@@ -19,23 +28,62 @@
set(CMAKE_Rust_FLAGS_RELWITHDEBINFO_INIT "-O -g")
set(CMAKE_Rust_FLAGS_MINSIZEREL_INIT "-C opt-level=z")
+block(
+ PROPAGATE
+ CMAKE_Rust_LINK_PIE_SUPPORTED
+ CMAKE_Rust_LINK_NO_PIE_SUPPORTED
+ CMAKE_Rust_COMPILE_OPTIONS_PIE
+ CMAKE_Rust_COMPILE_OPTIONS_PIC
+ CMAKE_Rust_LINK_OPTIONS_PIE
+ CMAKE_Rust_LINK_OPTIONS_NO_PIE
+ )
+ execute_process(
+ COMMAND "${CMAKE_Rust_COMPILER}" --print relocation-models
+ OUTPUT_VARIABLE RUSTC_OUTPUT
+ ERROR_VARIABLE RUSTC_ERROR
+ RESULT_VARIABLE RUSTC_EXITCODE
+ )
+ if(RUSTC_EXITCODE EQUAL "0")
+ string(REPLACE "\n" ";" RUSTC_OUTPUT_LINES "${RUSTC_OUTPUT}")
+ list(TRANSFORM RUSTC_OUTPUT_LINES STRIP)
+ if("pic" IN_LIST RUSTC_OUTPUT_LINES)
+ set(CMAKE_Rust_COMPILE_OPTIONS_PIC -C relocation-model=pic)
+ endif()
+ if("pie" IN_LIST RUSTC_OUTPUT_LINES)
+ set(CMAKE_Rust_LINK_PIE_SUPPORTED TRUE)
+ set(CMAKE_Rust_COMPILE_OPTIONS_PIE -C relocation-model=pie)
+ set(CMAKE_Rust_LINK_OPTIONS_PIE -C relocation-model=pie)
+ else()
+ set(CMAKE_Rust_LINK_PIE_SUPPORTED FALSE)
+ endif()
+ if("static" IN_LIST RUSTC_OUTPUT_LINES)
+ set(CMAKE_Rust_LINK_NO_PIE_SUPPORTED TRUE)
+ set(CMAKE_Rust_LINK_OPTIONS_NO_PIE -C relocation-model=static)
+ else()
+ set(CMAKE_Rust_LINK_NO_PIE_SUPPORTED FALSE)
+ endif()
+ else()
+ string(REPLACE "\n" "\n " RUSTC_ERROR " ${RUSTC_ERROR}")
+ message(FATAL_ERROR "Failed to check PIC/PIE support in rustc:\n${RUSTC_ERROR}")
+ endif()
+endblock()
+
cmake_initialize_per_config_variable(CMAKE_Rust_FLAGS "Flags used by the Rust compiler")
+if(NOT CMAKE_Rust_COMPILE_OBJECT)
+ set(CMAKE_Rust_COMPILE_OBJECT "<CMAKE_Rust_COMPILER> --crate-type=rlib <FLAGS> --emit=<RUST_EMIT>,dep-info=<DEP_FILE> -o <OBJECT> <SOURCE>")
+endif()
+
if(NOT CMAKE_Rust_CREATE_STATIC_LIBRARY)
- set(CMAKE_Rust_CREATE_STATIC_LIBRARY "${CMAKE_Rust_COMPILER} <LANGUAGE_COMPILE_FLAGS> --crate-type=staticlib <RUST_SOURCES> -o <TARGET> -C link-args=\"<RUST_OBJECT_DEPS>\"")
+ set(CMAKE_Rust_CREATE_STATIC_LIBRARY "${CMAKE_Rust_COMPILER} <LANGUAGE_COMPILE_FLAGS> --crate-type=staticlib --emit=link,dep-info=<DEP_FILE> <RUST_MAIN_CRATE_ROOT> -o <TARGET> <RUST_LINK_CRATES> <RUST_NATIVE_OBJECTS>")
endif()
if(NOT CMAKE_Rust_CREATE_SHARED_LIBRARY)
- set(CMAKE_Rust_CREATE_SHARED_LIBRARY "${CMAKE_Rust_COMPILER} <LANGUAGE_COMPILE_FLAGS> --crate-type=cdylib <RUST_SOURCES> -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> -C link-args=\"<RUST_OBJECT_DEPS>\"")
-endif()
-
-# Deadcode warnings are not useful when generating object files.
-if(NOT CMAKE_Rust_COMPILE_OBJECT)
- set(CMAKE_Rust_COMPILE_OBJECT "${CMAKE_Rust_COMPILER} <FLAGS> -A dead_code --crate-type=lib --emit=obj=<OBJECT>,dep-info=<DEP_FILE> <SOURCE>")
+ set(CMAKE_Rust_CREATE_SHARED_LIBRARY "${CMAKE_Rust_COMPILER} <LANGUAGE_COMPILE_FLAGS> --crate-type=cdylib --emit=link,dep-info=<DEP_FILE> <RUST_MAIN_CRATE_ROOT> -o <TARGET> <RUST_LINK_CRATES> <RUST_NATIVE_OBJECTS> <LINK_FLAGS> <LINK_LIBRARIES>")
endif()
if(NOT CMAKE_Rust_LINK_EXECUTABLE)
- set(CMAKE_Rust_LINK_EXECUTABLE "${CMAKE_Rust_COMPILER} <FLAGS> --crate-type=bin <RUST_SOURCES> -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> -C link-args=\"<RUST_OBJECT_DEPS>\"")
+ set(CMAKE_Rust_LINK_EXECUTABLE "${CMAKE_Rust_COMPILER} <FLAGS> --crate-type=bin --emit=link,dep-info=<DEP_FILE> <RUST_MAIN_CRATE_ROOT> -o <TARGET> <RUST_LINK_CRATES> <RUST_NATIVE_OBJECTS> <LINK_FLAGS> <LINK_LIBRARIES>")
endif()
set(CMAKE_Rust_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake
index d32fb6c..62225c6 100644
--- a/Modules/CMakeTestCCompiler.cmake
+++ b/Modules/CMakeTestCCompiler.cmake
@@ -55,11 +55,9 @@
# Puts test result in cache variable.
try_compile(CMAKE_C_COMPILER_WORKS
SOURCE_FROM_VAR testCCompiler.c __TestCompiler_testCCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_C_COMPILER_OUTPUT)
unset(__TestCompiler_testCCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_C_COMPILER_WORKS ${CMAKE_C_COMPILER_WORKS})
- unset(CMAKE_C_COMPILER_WORKS CACHE)
__TestCompiler_restoreTryCompileTargetType()
if(NOT CMAKE_C_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake
index d34ae92..30b0faf 100644
--- a/Modules/CMakeTestCSharpCompiler.cmake
+++ b/Modules/CMakeTestCSharpCompiler.cmake
@@ -33,12 +33,10 @@
# Puts test result in cache variable.
try_compile(CMAKE_CSharp_COMPILER_WORKS
SOURCE_FROM_VAR testCSharpCompiler.cs __TestCompiler_testCSharpCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_CSharp_COMPILER_OUTPUT
)
unset(__TestCompiler_testCSharpCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_CSharp_COMPILER_WORKS})
- unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
set(CSharp_TEST_WAS_RUN 1)
endif()
diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake
index fbeadf7..32c9144 100644
--- a/Modules/CMakeTestCUDACompiler.cmake
+++ b/Modules/CMakeTestCUDACompiler.cmake
@@ -47,12 +47,10 @@
# Puts test result in cache variable.
try_compile(CMAKE_CUDA_COMPILER_WORKS
SOURCE_FROM_VAR main.cu __TestCompiler_testCudaCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_CUDA_COMPILER_OUTPUT)
unset(__TestCompiler_testCudaCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_CUDA_COMPILER_WORKS})
- unset(CMAKE_CUDA_COMPILER_WORKS CACHE)
if(NOT CMAKE_CUDA_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
string(REPLACE "\n" "\n " _output "${__CMAKE_CUDA_COMPILER_OUTPUT}")
diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake
index 5c35426..c005011 100644
--- a/Modules/CMakeTestCXXCompiler.cmake
+++ b/Modules/CMakeTestCXXCompiler.cmake
@@ -55,6 +55,7 @@
# Puts test result in cache variable.
try_compile(CMAKE_CXX_COMPILER_WORKS
SOURCE_FROM_VAR testCXXCompiler.cxx __TestCompiler_testCXXCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_CXX_COMPILER_OUTPUT)
if(DEFINED __CMAKE_SAVED_CXX_SCAN_FOR_MODULES)
set(CMAKE_CXX_SCAN_FOR_MODULES "${__CMAKE_SAVED_CXX_SCAN_FOR_MODULES}")
@@ -63,9 +64,6 @@
unset(CMAKE_CXX_SCAN_FOR_MODULES)
endif()
unset(__TestCompiler_testCXXCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_CXX_COMPILER_WORKS ${CMAKE_CXX_COMPILER_WORKS})
- unset(CMAKE_CXX_COMPILER_WORKS CACHE)
__TestCompiler_restoreTryCompileTargetType()
if(NOT CMAKE_CXX_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake
index bf4100e..04c790b 100644
--- a/Modules/CMakeTestFortranCompiler.cmake
+++ b/Modules/CMakeTestFortranCompiler.cmake
@@ -48,11 +48,9 @@
# Puts test result in cache variable.
try_compile(CMAKE_Fortran_COMPILER_WORKS
SOURCE_FROM_VAR testFortranCompiler.f __TestCompiler_testFortranCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE OUTPUT)
unset(__TestCompiler_testFortranCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_Fortran_COMPILER_WORKS ${CMAKE_Fortran_COMPILER_WORKS})
- unset(CMAKE_Fortran_COMPILER_WORKS CACHE)
if(NOT CMAKE_Fortran_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
string(REPLACE "\n" "\n " _output "${OUTPUT}")
diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake
index ed1df10..57994b9 100644
--- a/Modules/CMakeTestHIPCompiler.cmake
+++ b/Modules/CMakeTestHIPCompiler.cmake
@@ -61,11 +61,9 @@
# Puts test result in cache variable.
try_compile(CMAKE_HIP_COMPILER_WORKS
SOURCE_FROM_VAR testHIPCompiler.hip __TestCompiler_testHIPCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_HIP_COMPILER_OUTPUT)
unset(__TestCompiler_testHIPCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_HIP_COMPILER_WORKS ${CMAKE_HIP_COMPILER_WORKS})
- unset(CMAKE_HIP_COMPILER_WORKS CACHE)
__TestCompiler_restoreTryCompileTargetType()
if(NOT CMAKE_HIP_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake
index 8003415..056c4ee 100644
--- a/Modules/CMakeTestOBJCCompiler.cmake
+++ b/Modules/CMakeTestOBJCCompiler.cmake
@@ -52,11 +52,9 @@
# Puts test result in cache variable.
try_compile(CMAKE_OBJC_COMPILER_WORKS
SOURCE_FROM_VAR testObjCCompiler.m __TestCompiler_testObjCCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT)
unset(__TestCompiler_testObjCCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_OBJC_COMPILER_WORKS})
- unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
__TestCompiler_restoreTryCompileTargetType()
if(NOT CMAKE_OBJC_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake
index 1b4bf60..dbdd2ba 100644
--- a/Modules/CMakeTestOBJCXXCompiler.cmake
+++ b/Modules/CMakeTestOBJCXXCompiler.cmake
@@ -51,11 +51,9 @@
# Puts test result in cache variable.
try_compile(CMAKE_OBJCXX_COMPILER_WORKS
SOURCE_FROM_VAR testObjCXXCompiler.mm __TestCompiler_testObjCXXCompilerSource
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT)
unset(__TestCompiler_testObjCXXCompilerSource)
- # Move result from cache to normal variable.
- set(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_OBJCXX_COMPILER_WORKS})
- unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE)
__TestCompiler_restoreTryCompileTargetType()
if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake
index 0abaabe..64751eb 100644
--- a/Modules/CMakeTestSwiftCompiler.cmake
+++ b/Modules/CMakeTestSwiftCompiler.cmake
@@ -30,10 +30,8 @@
"}")
try_compile(CMAKE_Swift_COMPILER_WORKS
SOURCE_FROM_VAR main.swift __CMAKE_Swift_TEST_SOURCE
+ NO_CACHE
OUTPUT_VARIABLE __CMAKE_Swift_COMPILER_OUTPUT)
- # Move result from cache to normal variable.
- set(CMAKE_Swift_COMPILER_WORKS ${CMAKE_Swift_COMPILER_WORKS})
- unset(CMAKE_Swift_COMPILER_WORKS CACHE)
set(Swift_TEST_WAS_RUN 1)
endif()
diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake
index ced2a81..f6a4e8b 100644
--- a/Modules/CheckIPOSupported.cmake
+++ b/Modules/CheckIPOSupported.cmake
@@ -199,14 +199,13 @@
PROJECT "${TRY_COMPILE_PROJECT_NAME}"
SOURCE_DIR "${srcdir}"
BINARY_DIR "${bindir}"
+ NO_CACHE
CMAKE_FLAGS
"-DCMAKE_VERBOSE_MAKEFILE=ON"
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON"
${_CMAKE_LANG_FLAGS}
OUTPUT_VARIABLE output
)
- set(_IPO_LANGUAGE_CHECK_RESULT "${_IPO_LANGUAGE_CHECK_RESULT}")
- unset(_IPO_LANGUAGE_CHECK_RESULT CACHE)
if(NOT _IPO_LANGUAGE_CHECK_RESULT)
_ipo_not_supported("check failed to compile")
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index 205c5f7..7b3bd45 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -20,43 +20,48 @@
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
endif()
-if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
- if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
- if (CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR)
- set(_clang_scan_deps_resource_dir
- " -resource-dir \"${CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR}\"")
- else()
- set(_clang_scan_deps_resource_dir "")
- endif ()
- if (CMAKE_HOST_WIN32)
- # `rename` doesn't overwrite and doesn't retry in case of "target file is
- # busy".
- set(_clang_scan_deps_mv "\"${CMAKE_COMMAND}\" -E rename")
- else ()
- set(_clang_scan_deps_mv "mv")
- endif ()
- string(CONCAT CMAKE_CXX_SCANDEP_SOURCE
- "\"${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}\""
- " -format=p1689"
- " --"
- " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>"
- " -x c++ <SOURCE> -c -o <OBJECT>"
- "${_clang_scan_deps_resource_dir}"
- " -MT <DYNDEP_FILE>"
- " -MD -MF <DEP_FILE>"
- # Write to a temporary file. If the scan fails, we do not want to update
- # the actual output file as `ninja` (at least) assumes that failed
- # commands either delete or leave output files alone. See Issue#25419.
- " > <DYNDEP_FILE>.tmp"
- # We cannot use `copy_if_different` as the rule does not have a feature
- # analogous to `ninja`'s `restat = 1`. It would also leave behind the
- # `.tmp` file.
- " && ${_clang_scan_deps_mv} <DYNDEP_FILE>.tmp <DYNDEP_FILE>")
- unset(_clang_scan_deps_resource_dir)
- unset(_clang_scan_deps_mv)
- set(CMAKE_CXX_MODULE_MAP_FORMAT "clang")
- set(CMAKE_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
- set(CMAKE_CXX_COMPILE_BMI
- "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> --precompile <SOURCE>")
+if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") OR
+ (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.1 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
+ if (CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR)
+ set(_clang_scan_deps_resource_dir
+ " -resource-dir \"${CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR}\"")
+ else()
+ set(_clang_scan_deps_resource_dir "")
+ endif ()
+ if (CMAKE_HOST_WIN32)
+ # `rename` doesn't overwrite and doesn't retry in case of "target file is
+ # busy".
+ set(_clang_scan_deps_mv "\"${CMAKE_COMMAND}\" -E rename")
+ else ()
+ set(_clang_scan_deps_mv "mv")
+ endif ()
+ if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
+ set(_clang "-clang:")
+ else()
+ set(_clang "")
endif()
+ string(CONCAT CMAKE_CXX_SCANDEP_SOURCE
+ "\"${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}\""
+ " -format=p1689"
+ " --"
+ " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>"
+ " -x c++ <SOURCE> -c ${_clang}-o ${_clang}<OBJECT>"
+ "${_clang_scan_deps_resource_dir}"
+ " ${_clang}-MT ${_clang}<DYNDEP_FILE>"
+ " ${_clang}-MD ${_clang}-MF ${_clang}<DEP_FILE>"
+ # Write to a temporary file. If the scan fails, we do not want to update
+ # the actual output file as `ninja` (at least) assumes that failed
+ # commands either delete or leave output files alone. See Issue#25419.
+ " > <DYNDEP_FILE>.tmp"
+ # We cannot use `copy_if_different` as the rule does not have a feature
+ # analogous to `ninja`'s `restat = 1`. It would also leave behind the
+ # `.tmp` file.
+ " && ${_clang_scan_deps_mv} <DYNDEP_FILE>.tmp <DYNDEP_FILE>")
+ unset(_clang_scan_deps_resource_dir)
+ unset(_clang_scan_deps_mv)
+ set(CMAKE_CXX_MODULE_MAP_FORMAT "clang")
+ set(CMAKE_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
+ set(CMAKE_CXX_COMPILE_BMI
+ "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${_clang}-o ${_clang}<OBJECT> --precompile <SOURCE>")
+ unset(_clang)
endif()
diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake
index 97e1adb..14c6cf2 100644
--- a/Modules/Compiler/IAR.cmake
+++ b/Modules/Compiler/IAR.cmake
@@ -23,6 +23,8 @@
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG")
set(CMAKE_${lang}_LINK_MODE LINKER)
+
+ set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "--warnings_are_errors")
endif()
set(CMAKE_${lang}_OUTPUT_EXTENSION_REPLACE 1)
diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake
index 51a62b6..5f8708d 100644
--- a/Modules/Compiler/NVHPC-C.cmake
+++ b/Modules/Compiler/NVHPC-C.cmake
@@ -22,4 +22,10 @@
set(CMAKE_C_DEPENDS_EXTRA_COMMANDS "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>")
endif()
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 26.3)
+ set(CMAKE_C23_STANDARD_COMPILE_OPTION -std=c23)
+ set(CMAKE_C23_EXTENSION_COMPILE_OPTION -std=gnu23)
+ set(CMAKE_C_STANDARD_LATEST 23)
+endif()
+
__compiler_nvhpc(C)
diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake
index 56daffb..5907b29 100644
--- a/Modules/Compiler/NVHPC-CXX.cmake
+++ b/Modules/Compiler/NVHPC-CXX.cmake
@@ -29,4 +29,11 @@
set(CMAKE_CXX_STANDARD_LATEST 23)
endif()
+if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 26.3)
+ set(CMAKE_CXX23_EXTENSION_COMPILE_OPTION -std=gnu++23) # -std=gnu++23 is now available
+ set(CMAKE_CXX26_STANDARD_COMPILE_OPTION -std=c++26)
+ set(CMAKE_CXX26_EXTENSION_COMPILE_OPTION -std=gnu++26)
+ set(CMAKE_CXX_STANDARD_LATEST 26)
+endif()
+
__compiler_nvhpc(CXX)
diff --git a/Modules/Compiler/OrangeC-C.cmake b/Modules/Compiler/OrangeC-C.cmake
index f0dfcd1..edf0da5 100644
--- a/Modules/Compiler/OrangeC-C.cmake
+++ b/Modules/Compiler/OrangeC-C.cmake
@@ -17,6 +17,13 @@
set(CMAKE_C_STANDARD_LATEST 11)
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "6.0.71")
+ set(CMAKE_C23_STANDARD_COMPILE_OPTION -2)
+ set(CMAKE_C23_EXTENSION_COMPILE_OPTION -2)
+
+ set(CMAKE_C_STANDARD_LATEST 23)
+endif()
+
__compiler_orangec(C)
#- 6.38 is the earliest version which version info is available in the preprocessor
__compiler_check_default_language_standard(C 6.38 11)
diff --git a/Modules/Compiler/OrangeC-CXX.cmake b/Modules/Compiler/OrangeC-CXX.cmake
index 575c09d..4827d7f 100644
--- a/Modules/Compiler/OrangeC-CXX.cmake
+++ b/Modules/Compiler/OrangeC-CXX.cmake
@@ -22,6 +22,14 @@
set(CMAKE_CXX_STANDARD_LATEST 14)
+if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_CXX17_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_CXX_STANDARD_LATEST 17)
+endif()
+
__compiler_orangec(CXX)
#- 6.38 is the earliest version which version info is available in the preprocessor
__compiler_check_default_language_standard(CXX 6.38 14)
diff --git a/Modules/Compiler/OrangeC.cmake b/Modules/Compiler/OrangeC.cmake
index 69628b8..27f0c8d 100644
--- a/Modules/Compiler/OrangeC.cmake
+++ b/Modules/Compiler/OrangeC.cmake
@@ -22,13 +22,14 @@
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
"<CMAKE_${lang}_COMPILER> -! -static -o <TARGET> <LINK_FLAGS> <OBJECTS> ")
- set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_${lang}_COMPILER> -! <FLAGS> -o <TARGET> --out-implib <TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES>")
+ set(CMAKE_${lang}_LINK_EXECUTABLE
+ "<CMAKE_${lang}_COMPILER> -! <FLAGS> -o <TARGET> --out-implib <TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "<CMAKE_${lang}_COMPILER> -! <FLAGS> -o <TARGET> --out-implib <TARGET_IMPLIB> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES>")
+ "<CMAKE_${lang}_COMPILER> -! <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> -o <TARGET> --out-implib <TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_${lang}_CREATE_SHARED_MODULE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}")
set(CMAKE_LIBRARY_PATH_FLAG "-L")
- set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-! -shared")
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@")
set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@")
diff --git a/Modules/Compiler/PellesC-C.cmake b/Modules/Compiler/PellesC-C.cmake
new file mode 100644
index 0000000..c97fa64
--- /dev/null
+++ b/Modules/Compiler/PellesC-C.cmake
@@ -0,0 +1,8 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file LICENSE.rst or https://cmake.org/licensing for details.
+
+include (Compiler/PellesC)
+__compiler_pellesc(C)
+
+set(CMAKE_C_OUTPUT_EXTENSION ".obj")
+set(CMAKE_C_VERBOSE_FLAG "-V2")
diff --git a/Modules/Compiler/PellesC-DetermineCompiler.cmake b/Modules/Compiler/PellesC-DetermineCompiler.cmake
new file mode 100644
index 0000000..c53e5e6
--- /dev/null
+++ b/Modules/Compiler/PellesC-DetermineCompiler.cmake
@@ -0,0 +1,8 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file LICENSE.rst or https://cmake.org/licensing for details.
+
+set(_compiler_id_pp_test "defined(__POCC__)")
+
+set(_compiler_id_version_compute "
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__POCC__/100)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__POCC__%100)")
diff --git a/Modules/Compiler/PellesC.cmake b/Modules/Compiler/PellesC.cmake
new file mode 100644
index 0000000..c53162b
--- /dev/null
+++ b/Modules/Compiler/PellesC.cmake
@@ -0,0 +1,7 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file LICENSE.rst or https://cmake.org/licensing for details.
+include_guard()
+
+macro(__compiler_pellesc lang)
+ set(CMAKE_${lang}_LINK_MODE LINKER)
+endmacro ()
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 02d8bd9..c40df1a 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -169,6 +169,46 @@
some platforms. The ``ExternalData_NO_SYMLINKS`` variable may be set
to disable use of symbolic links and enable use of copies instead.
+.. variable:: ExternalData_STATE_ROOT
+
+ .. versionadded:: 4.4
+
+ The ``ExternalData_STATE_ROOT`` variable may be set to place module-managed
+ metadata outside ``ExternalData_BINARY_ROOT``. When set, ``ExternalData``
+ stores its hash records under this directory while still materializing real
+ data files under ``ExternalData_BINARY_ROOT``. By default, hash records
+ continue to be placed next to the materialized data.
+
+.. variable:: ExternalData_LINK_MODE
+
+ .. versionadded:: 4.4
+
+ The ``ExternalData_LINK_MODE`` variable selects how real data files are
+ exposed under ``ExternalData_BINARY_ROOT``.
+
+ The value may be one of:
+
+ ``auto``
+ Try each of the supported modes until one succeeds.
+ The default order is ``hardlink -> symlink -> copy`` on Windows
+ and ``symlink -> hardlink -> copy`` on other platforms.
+
+ ``hardlink``
+ Materialize paths as hard links to the real files.
+
+ ``symlink``
+ Materialize paths as symbolic links to the real files.
+
+ ``copy``
+ Materialize paths as copies of the real files.
+
+ Or, the value may be a :ref:`semicolon-separated list <CMake Language Lists>`
+ of ``hardlink``, ``symlink``, and ``copy`` to try the modes in the order
+ specified until one succeeds.
+
+ When ``ExternalData_NO_SYMLINKS`` is set, the ``symlink`` mode is removed
+ from automatic selection and cannot be requested explicitly.
+
.. variable:: ExternalData_OBJECT_STORES
The ``ExternalData_OBJECT_STORES`` variable may be set to a list of local
@@ -541,7 +581,7 @@
list(GET tuple 2 exts)
string(REPLACE "+" ";" exts_list "${exts}")
list(GET exts_list 0 first_ext)
- set(stamp "-hash-stamp")
+ _ExternalData_compute_stamp_file("${file}" stamp_file)
if(NOT DEFINED "_ExternalData_FILE_${file}")
set("_ExternalData_FILE_${file}" 1)
get_property(added DIRECTORY PROPERTY "_ExternalData_FILE_${file}")
@@ -554,10 +594,11 @@
# List the real file as a second output in case it is a broken link.
# The files must be listed in this order so CMake can hide from the
# make tool that a symlink target may not be newer than the input.
- OUTPUT "${file}${stamp}" "${file}"
+ OUTPUT "${stamp_file}" "${file}"
# Run the data fetch/update script.
COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
-Dfile=${file} -Dname=${name} -Dexts=${exts}
+ -Dstamp_file=${stamp_file}
-DExternalData_ACTION=fetch
-DExternalData_SHOW_PROGRESS=${_ExternalData_add_target_SHOW_PROGRESS}
-DExternalData_CONFIG=${config}
@@ -566,7 +607,7 @@
MAIN_DEPENDENCY "${name}${first_ext}"
)
endif()
- list(APPEND files "${file}${stamp}")
+ list(APPEND files "${stamp_file}")
endif()
endforeach()
@@ -636,12 +677,40 @@
endfunction()
function(_ExternalData_atomic_write file content)
+ get_filename_component(dir "${file}" DIRECTORY)
+ file(MAKE_DIRECTORY "${dir}")
_ExternalData_random(random)
set(tmp "${file}.tmp${random}")
file(WRITE "${tmp}" "${content}")
file(RENAME "${tmp}" "${file}")
endfunction()
+function(_ExternalData_compute_stamp_file file var_stamp)
+ if(DEFINED ExternalData_STATE_ROOT AND NOT "${ExternalData_STATE_ROOT}" STREQUAL "")
+ _ExternalData_compute_state_relative_path("${file}" relfile)
+ set(stamp_file "${ExternalData_STATE_ROOT}/${relfile}-hash-stamp")
+ else()
+ set(stamp_file "${file}-hash-stamp")
+ endif()
+ set(${var_stamp} "${stamp_file}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_compute_state_relative_path file var_relfile)
+ if(NOT ExternalData_BINARY_ROOT)
+ set(top_bin "${CMAKE_BINARY_DIR}")
+ else()
+ set(top_bin "${ExternalData_BINARY_ROOT}")
+ endif()
+ file(RELATIVE_PATH relfile "${top_bin}" "${file}")
+ if(IS_ABSOLUTE "${relfile}" OR "${relfile}" MATCHES "^\\.\\./")
+ message(FATAL_ERROR
+ "File path is not under ExternalData_BINARY_ROOT:\n"
+ " file = ${file}\n"
+ " ExternalData_BINARY_ROOT = ${top_bin}")
+ endif()
+ set(${var_relfile} "${relfile}" PARENT_SCOPE)
+endfunction()
+
function(_ExternalData_link_content name var_ext)
if("${ExternalData_LINK_CONTENT}" MATCHES "^(${_ExternalData_REGEX_ALGO})$")
set(algo "${ExternalData_LINK_CONTENT}")
@@ -971,33 +1040,103 @@
"Neither ExternalData_URL_TEMPLATES nor ExternalData_OBJECT_STORES is set!")
endif()
+function(_ExternalData_compute_link_target src dst var_tgt)
+ get_filename_component(dst_dir "${dst}" PATH)
+ set(tgt "${src}")
+ if(relative_top)
+ # Use relative path if files are close enough.
+ file(RELATIVE_PATH relsrc "${relative_top}" "${src}")
+ file(RELATIVE_PATH reldst "${relative_top}" "${dst}")
+ if(NOT IS_ABSOLUTE "${relsrc}" AND NOT "${relsrc}" MATCHES "^\\.\\./" AND
+ NOT IS_ABSOLUTE "${reldst}" AND NOT "${reldst}" MATCHES "^\\.\\./")
+ file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
+ endif()
+ endif()
+ set(${var_tgt} "${tgt}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_try_link_mode mode src dst var_result)
+ if(mode STREQUAL "copy")
+ file(COPY_FILE "${src}" "${dst}" RESULT result INPUT_MAY_BE_RECENT)
+ elseif(mode STREQUAL "hardlink")
+ file(CREATE_LINK "${src}" "${dst}" RESULT result)
+ elseif(mode STREQUAL "symlink")
+ _ExternalData_compute_link_target("${src}" "${dst}" tgt)
+ file(CREATE_LINK "${tgt}" "${dst}" RESULT result SYMBOLIC)
+ else()
+ set(result "Unsupported ExternalData_LINK_MODE `${mode}`")
+ endif()
+ set(${var_result} "${result}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_get_auto_link_modes var_modes)
+ if(CMAKE_HOST_WIN32)
+ set(modes hardlink)
+ if(NOT ExternalData_NO_SYMLINKS)
+ list(APPEND modes symlink)
+ endif()
+ list(APPEND modes copy)
+ else()
+ if(NOT ExternalData_NO_SYMLINKS)
+ list(APPEND modes symlink)
+ endif()
+ list(APPEND modes hardlink copy)
+ endif()
+ set(${var_modes} "${modes}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_get_requested_link_modes var_modes)
+ if(DEFINED ExternalData_LINK_MODE AND NOT "${ExternalData_LINK_MODE}" STREQUAL "")
+ set(requested_modes "${ExternalData_LINK_MODE}")
+ else()
+ set(requested_modes auto)
+ endif()
+ string(TOLOWER "${requested_modes}" requested_modes_lower)
+
+ if(requested_modes_lower STREQUAL "auto")
+ _ExternalData_get_auto_link_modes(modes)
+ else()
+ set(modes)
+ foreach(mode IN LISTS requested_modes)
+ string(TOLOWER "${mode}" mode_lower)
+ if(mode_lower STREQUAL "copy" OR mode_lower STREQUAL "hardlink")
+ list(APPEND modes "${mode_lower}")
+ elseif(mode_lower STREQUAL "symlink")
+ if(ExternalData_NO_SYMLINKS)
+ message(FATAL_ERROR
+ "ExternalData_LINK_MODE with `symlink` conflicts with NO_SYMLINKS")
+ endif()
+ list(APPEND modes symlink)
+ else()
+ message(FATAL_ERROR
+ "ExternalData_LINK_MODE must be `auto` or list: hardlink, symlink, copy")
+ endif()
+ endforeach()
+ endif()
+
+ set(${var_modes} "${modes}" PARENT_SCOPE)
+endfunction()
+
function(_ExternalData_link_or_copy src dst)
# Create a temporary file first.
get_filename_component(dst_dir "${dst}" PATH)
file(MAKE_DIRECTORY "${dst_dir}")
_ExternalData_random(random)
set(tmp "${dst}.tmp${random}")
- if(UNIX AND NOT ExternalData_NO_SYMLINKS)
- # Create a symbolic link.
- set(tgt "${src}")
- if(relative_top)
- # Use relative path if files are close enough.
- file(RELATIVE_PATH relsrc "${relative_top}" "${src}")
- file(RELATIVE_PATH relfile "${relative_top}" "${dst}")
- if(NOT IS_ABSOLUTE "${relsrc}" AND NOT "${relsrc}" MATCHES "^\\.\\./" AND
- NOT IS_ABSOLUTE "${reldst}" AND NOT "${reldst}" MATCHES "^\\.\\./")
- file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
- endif()
+ _ExternalData_get_requested_link_modes(_ExternalData_link_modes)
+
+ unset(result)
+ foreach(_ExternalData_mode IN LISTS _ExternalData_link_modes)
+ _ExternalData_try_link_mode("${_ExternalData_mode}" "${src}" "${tmp}" result)
+ if(NOT result)
+ break()
endif()
- # Create link (falling back to copying if there's a problem).
- file(CREATE_LINK "${tgt}" "${tmp}" RESULT result COPY_ON_ERROR SYMBOLIC)
- else()
- # Create a copy.
- file(COPY_FILE "${src}" "${tmp}" RESULT result INPUT_MAY_BE_RECENT)
- endif()
+ file(REMOVE "${tmp}")
+ endforeach()
+
if(result)
file(REMOVE "${tmp}")
- message(FATAL_ERROR "Failed to create:\n \"${tmp}\"\nfrom:\n \"${obj}\"\nwith error:\n ${result}")
+ message(FATAL_ERROR "Failed to create:\n \"${tmp}\"\nfrom:\n \"${src}\"\nwith error:\n ${result}")
endif()
# Atomically create/replace the real destination.
@@ -1235,10 +1374,16 @@
message(FATAL_ERROR "${errorMsg}")
endif()
# Check if file already corresponds to the object.
- set(stamp "-hash-stamp")
+ if(NOT DEFINED stamp_file OR "${stamp_file}" STREQUAL "")
+ if(DEFINED ExternalData_STATE_ROOT AND NOT "${ExternalData_STATE_ROOT}" STREQUAL "")
+ message(FATAL_ERROR
+ "stamp_file must be provided when ExternalData_STATE_ROOT is set")
+ endif()
+ set(stamp_file "${file}-hash-stamp")
+ endif()
set(file_up_to_date 0)
- if(EXISTS "${file}" AND EXISTS "${file}${stamp}")
- file(READ "${file}${stamp}" f_hash)
+ if(EXISTS "${file}" AND EXISTS "${stamp_file}")
+ file(READ "${stamp_file}" f_hash)
string(STRIP "${f_hash}" f_hash)
if("${f_hash}" STREQUAL "${hash}")
set(file_up_to_date 1)
@@ -1253,7 +1398,7 @@
endif()
# Atomically update the hash/timestamp file to record the object referenced.
- _ExternalData_atomic_write("${file}${stamp}" "${hash}\n")
+ _ExternalData_atomic_write("${stamp_file}" "${hash}\n")
elseif("${ExternalData_ACTION}" STREQUAL "local")
foreach(v file name)
if(NOT DEFINED "${v}")
diff --git a/Modules/ExternalData_config.cmake.in b/Modules/ExternalData_config.cmake.in
index 18be6b3..69cf0f5 100644
--- a/Modules/ExternalData_config.cmake.in
+++ b/Modules/ExternalData_config.cmake.in
@@ -3,4 +3,6 @@
set(ExternalData_TIMEOUT_INACTIVITY "@ExternalData_TIMEOUT_INACTIVITY@")
set(ExternalData_TIMEOUT_ABSOLUTE "@ExternalData_TIMEOUT_ABSOLUTE@")
set(ExternalData_NO_SYMLINKS "@ExternalData_NO_SYMLINKS@")
+set(ExternalData_STATE_ROOT "@ExternalData_STATE_ROOT@")
+set(ExternalData_LINK_MODE "@ExternalData_LINK_MODE@")
@_ExternalData_CONFIG_CODE@
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index fefcd27..1045259 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -446,6 +446,31 @@
unintended changes or failed builds resulting from conflicts during
rebase operations.
+The following variables can be set to control the retry behavior for
+``git clone`` operations:
+
+.. variable:: CMAKE_EP_GIT_CLONE_RETRY_COUNT
+
+ .. versionadded:: 4.4
+
+ Specifies the number of times to retry a ``git clone`` operation if it
+ fails. The default is ``2`` retries. The first attempt is not counted
+ as a retry, so the total number of attempts is the retry count plus one.
+ This variable should not be set by a project, it is intended for the user
+ to set. It is primarily useful when dealing with intermittent network
+ issues or rate limiting from git hosting services.
+
+.. variable:: CMAKE_EP_GIT_CLONE_RETRY_DELAY
+
+ .. versionadded:: 4.4
+
+ Specifies the delay in seconds between retry attempts for git clone
+ operations. The default is ``0`` seconds (no delay between retries).
+ This variable should not be set by a project, it is intended for the
+ user to set. Setting a delay can be helpful when dealing with rate
+ limiting from git hosting services, where immediate retries would
+ also be rejected.
+
Subversion
~~~~~~~~~~
diff --git a/Modules/ExternalProject/gitclone.cmake.in b/Modules/ExternalProject/gitclone.cmake.in
index 449bcb3..19a7eb4 100644
--- a/Modules/ExternalProject/gitclone.cmake.in
+++ b/Modules/ExternalProject/gitclone.cmake.in
@@ -30,10 +30,15 @@
message(FATAL_ERROR "Failed to remove directory: '@source_dir@'")
endif()
-# try the clone 3 times in case there is an odd git clone issue
+# try the clone 1 + N times in case there is an odd git clone issue
set(error_code 1)
set(number_of_tries 0)
-while(error_code AND number_of_tries LESS 3)
+math(EXPR max_tries "1 + @git_clone_retries@")
+while(error_code AND number_of_tries LESS ${max_tries})
+ if(number_of_tries GREATER 0 AND @git_clone_retry_delay@ GREATER 0)
+ message(STATUS "Retry #${number_of_tries}, waiting @git_clone_retry_delay@ seconds before next attempt...")
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep @git_clone_retry_delay@)
+ endif()
execute_process(
COMMAND "@git_EXECUTABLE@"
clone @git_clone_options@ "@git_repository@" "@src_name@"
@@ -47,7 +52,7 @@
message(NOTICE "Had to git clone more than once: ${number_of_tries} times.")
endif()
if(error_code)
- message(FATAL_ERROR "Failed to clone repository: '@git_repository@'")
+ message(FATAL_ERROR "Failed to clone repository:\n '@git_repository@'")
endif()
execute_process(
diff --git a/Modules/ExternalProject/shared_internal_commands.cmake b/Modules/ExternalProject/shared_internal_commands.cmake
index b7077ef..64ad3e3 100644
--- a/Modules/ExternalProject/shared_internal_commands.cmake
+++ b/Modules/ExternalProject/shared_internal_commands.cmake
@@ -397,6 +397,8 @@
gitclone_stampfile
tls_version
tls_verify
+ git_clone_retries
+ git_clone_retry_delay
)
if(NOT Git_VERSION VERSION_LESS 1.8.5)
@@ -979,6 +981,16 @@
get_filename_component(src_name "${source_dir}" NAME)
get_filename_component(work_dir "${source_dir}" PATH)
+ # Get retry configuration from variables with defaults
+ set(git_clone_retries "${CMAKE_EP_GIT_CLONE_RETRY_COUNT}")
+ if("${git_clone_retries}" STREQUAL "")
+ set(git_clone_retries 2)
+ endif()
+ set(git_clone_retry_delay "${CMAKE_EP_GIT_CLONE_RETRY_DELAY}")
+ if("${git_clone_retry_delay}" STREQUAL "")
+ set(git_clone_retry_delay 0)
+ endif()
+
# Since git clone doesn't succeed if the non-empty source_dir exists,
# create a cmake script to invoke as download command.
# The script will delete the source directory and then call git clone.
@@ -1003,6 +1015,8 @@
${stamp_dir}/${name}-gitclone-lastrun.txt
"${tls_version}"
"${tls_verify}"
+ "${git_clone_retries}"
+ "${git_clone_retry_delay}"
)
set(comment "Performing download step (git clone) for '${name}'")
set(cmd ${CMAKE_COMMAND}
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 80152f6..12d5f3b 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -1866,6 +1866,8 @@
set(__FETCHCONTENT_CACHED_INFO "")
set(__passthrough_vars
CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY
+ CMAKE_EP_GIT_CLONE_RETRY_COUNT
+ CMAKE_EP_GIT_CLONE_RETRY_DELAY
CMAKE_TLS_VERSION
CMAKE_TLS_VERIFY
CMAKE_TLS_CAINFO
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 231700a..5e3b365 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -1326,6 +1326,33 @@
set(${prefix}_OUTPUT_NAME ${${prefix}_NAME})
endif()
+ if(NOT ${prefix}_SRC)
+ message(FATAL_ERROR "[MATLAB] The MEX source files cannot be empty")
+ endif()
+
+ set(languages "")
+ foreach(src_file IN LISTS ${prefix}_SRC)
+ get_filename_component(ext ${src_file} EXT)
+ if(ext STREQUAL ".c")
+ list(APPEND languages "C")
+ elseif(ext STREQUAL ".cpp" OR ext STREQUAL ".cxx" OR ext STREQUAL ".c++" OR ext STREQUAL ".cc")
+ list(APPEND languages "CXX")
+ elseif(ext MATCHES "\\.[fF](90|95|03|08)?$" OR ext STREQUAL ".for")
+ list(APPEND languages "Fortran")
+ endif()
+ endforeach()
+
+ if("CXX" IN_LIST languages)
+ set(language "CXX")
+ elseif("C" IN_LIST languages)
+ set(language "C")
+ elseif("Fortran" IN_LIST languages)
+ set(language "Fortran")
+ else()
+ set(language "CXX")
+ message(STATUS "No standard C, CXX or Fortran source files, the target language is set to CXX")
+ endif()
+
if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file
# Compilers officially supported by Matlab 9.1 (R2016b):
# MinGW 4.9, MSVC 2012, Intel C++ 2013, Xcode 6, GCC 4.9
@@ -1333,25 +1360,26 @@
# Other compilers (Clang) may support the -w flag and can be added here.
set(_Matlab_silenceable_compilers AppleClang Clang GNU Intel IntelLLVM MSVC)
- # Add the correct version file depending on which languages are enabled in the project
- if(CMAKE_C_COMPILER_LOADED)
- # If C is enabled, use the .c file as it will work fine also with C++
+ # Add the correct version file depending on the languages of the source files
+ if(language STREQUAL "C")
+ # For C source files, use the .c file
set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c")
# Silence warnings for version source file
if("${CMAKE_C_COMPILER_ID}" IN_LIST _Matlab_silenceable_compilers)
set_source_files_properties("${MEX_VERSION_FILE}" PROPERTIES COMPILE_OPTIONS -w)
endif()
- elseif(CMAKE_CXX_COMPILER_LOADED)
- # If C is not enabled, check if CXX is enabled and use the .cpp file
- # to avoid that the .c file is silently ignored
+ elseif(language STREQUAL "CXX")
+ # For CXX source files, use the .cpp file
set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp")
if("${CMAKE_CXX_COMPILER_ID}" IN_LIST _Matlab_silenceable_compilers)
set_source_files_properties("${MEX_VERSION_FILE}" PROPERTIES COMPILE_OPTIONS -w)
endif()
+ elseif(language STREQUAL "Fortran")
+ # For Fortran source files, use the .F file
+ set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/fortran_mexapi_version.F")
else()
- # If neither C or CXX is enabled, warn because we cannot add the source.
- # TODO: add support for fortran mex files
- message(WARNING "[MATLAB] matlab_add_mex requires that at least C or CXX are enabled languages")
+ # If neither C, CXX or Fortran source files are provided, warn because we cannot add the source.
+ message(WARNING "[MATLAB] matlab_add_mex requires that the input source files are written in C, CXX or Fortran")
endif()
endif()
@@ -1433,9 +1461,16 @@
if (MSVC)
- string(APPEND _link_flags " /EXPORT:mexFunction")
- if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version
- string(APPEND _link_flags " /EXPORT:mexfilerequiredapiversion")
+ if(language STREQUAL "C" OR language STREQUAL "CXX")
+ string(APPEND _link_flags " /EXPORT:mexFunction")
+ if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version
+ string(APPEND _link_flags " /EXPORT:mexfilerequiredapiversion")
+ endif()
+ elseif(language STREQUAL "Fortran")
+ string(APPEND _link_flags " /EXPORT:MEXFUNCTION")
+ if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version
+ string(APPEND _link_flags " /EXPORT:MEXFILEREQUIREDAPIVERSION")
+ endif()
endif()
set_property(TARGET ${${prefix}_NAME} APPEND PROPERTY LINK_FLAGS ${_link_flags})
@@ -1448,9 +1483,17 @@
else()
if(Matlab_VERSION_STRING VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b)
- set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/mexFunction.map)
+ if(language STREQUAL "C" OR language STREQUAL "CXX")
+ set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/mexFunction.map)
+ elseif(language STREQUAL "Fortran")
+ set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/fexport.map)
+ endif()
else() # For 9.1 (R2016b) and newer
- set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/c_exportsmexfileversion.map)
+ if(language STREQUAL "C" OR language STREQUAL "CXX")
+ set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/c_exportsmexfileversion.map)
+ elseif(language STREQUAL "Fortran")
+ set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/fortran_exportsmexfileversion.map)
+ endif()
endif()
if(NOT Matlab_VERSION_STRING VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?)
@@ -1573,6 +1616,7 @@
find_program(
_matlab_current_program
+ NO_CACHE
NAMES matlab
${_find_matlab_options}
DOC "Matlab main program"
@@ -1588,14 +1632,12 @@
set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version")
set(Matlab_OR_MCR_INTERNAL ${matlab_or_mcr} CACHE INTERNAL "Whether Matlab root contains MATLAB or MCR")
unset(_matlab_current_program)
- unset(_matlab_current_program CACHE)
return()
endif()
# full real path for path comparison
get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH)
unset(_matlab_current_program)
- unset(_matlab_current_program CACHE)
# is it the same as the previous one?
if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT)
@@ -1747,6 +1789,7 @@
# If set by the user, this won't change.
find_program(
_matlab_main_tmp
+ NO_CACHE
NAMES matlab)
if(_matlab_main_tmp)
@@ -1766,11 +1809,11 @@
# We found the Matlab program
list(APPEND _matlab_possible_roots "MATLAB" "NOTFOUND" ${_matlab_current_location})
- # we remove this from the CACHE
- unset(_matlab_main_tmp CACHE)
+ unset(_matlab_main_tmp)
else()
find_program(
_matlab_mex_tmp
+ NO_CACHE
NAMES mex)
if(_matlab_mex_tmp)
# we then populate the list of roots, with empty version
@@ -1789,7 +1832,7 @@
# We found the Matlab program
list(APPEND _matlab_possible_roots "MCR" "NOTFOUND" ${_mex_current_location})
- unset(_matlab_mex_tmp CACHE)
+ unset(_matlab_mex_tmp)
else()
if(MATLAB_FIND_DEBUG)
message(STATUS "[MATLAB] mex compiler not found")
diff --git a/Modules/FindODBC.cmake b/Modules/FindODBC.cmake
index e8692bd..69c6ddb 100644
--- a/Modules/FindODBC.cmake
+++ b/Modules/FindODBC.cmake
@@ -219,13 +219,14 @@
foreach(_lib IN LISTS _odbc_required_libs_names)
find_library(_lib_path
+ NO_CACHE
NAMES ${_lib}
PATHS ${_odbc_lib_paths} # system paths or collected from ODBC_CONFIG
PATH_SUFFIXES odbc)
if(_lib_path)
list(APPEND _odbc_required_libs_paths ${_lib_path})
endif()
- unset(_lib_path CACHE)
+ unset(_lib_path)
endforeach()
endif()
diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake
index 2111893..eb5f723 100644
--- a/Modules/FindVulkan.cmake
+++ b/Modules/FindVulkan.cmake
@@ -278,6 +278,51 @@
The path to the DirectX shader compiler CLI tool.
+``Vulkan_Layer_API_DUMP_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `api_dump` Vulkan Layer library.
+
+``Vulkan_Layer_CRASH_DIAGNOSTIC_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `crash_diagnostic` Vulkan Layer library.
+
+``Vulkan_Layer_GFXRECONSTRUCT_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `gfxreconstruct` Vulkan Layer library.
+
+``Vulkan_Layer_KHRONOS_PROFILES_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `khronos_profiles` Vulkan Layer library.
+
+``Vulkan_Layer_KHRONOS_SHADER_OBJECT_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `khronos_shader_object` Vulkan Layer library.
+
+``Vulkan_Layer_KHRONOS_SYNCHRONIZATION2_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `khronos_synchronization2` Vulkan Layer library.
+
+``Vulkan_Layer_KHRONOS_VALIDATION_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `khronos_validation` Vulkan Layer library.
+
+``Vulkan_Layer_MONITOR_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `monitor` Vulkan Layer library.
+
+``Vulkan_Layer_SCREENSHOT_LIBRARY``
+ .. versionadded:: 4.4
+
+ Path to the `screenshot` Vulkan Layer library.
+
Hints
^^^^^
@@ -420,6 +465,31 @@
)
mark_as_advanced(Vulkan_LIBRARY)
+# On iOS search for Validation Layers, which must be explicitly linked.
+if (IOS)
+ foreach(layer IN ITEMS
+ api_dump
+ crash_diagnostic
+ gfxreconstruct
+ khronos_profiles
+ khronos_shader_object
+ khronos_synchronization2
+ khronos_validation
+ monitor
+ screenshot
+ )
+ string(TOUPPER "${layer}" LAYER)
+ find_library(Vulkan_Layer_${LAYER}_LIBRARY
+ NAMES VkLayer_${layer}
+ HINTS
+ ${_Vulkan_hint_library_search_paths}
+ OPTIONAL
+ )
+ mark_as_advanced(Vulkan_Layer_${LAYER}_LIBRARY)
+ endforeach()
+endif()
+
+# Search for requested components.
if(glslc IN_LIST Vulkan_FIND_COMPONENTS)
find_program(Vulkan_GLSLC_EXECUTABLE
NAMES glslc
diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake
index d559ab7..a90425f 100644
--- a/Modules/FortranCInterface.cmake
+++ b/Modules/FortranCInterface.cmake
@@ -420,6 +420,7 @@
TARGET VerifyFortranC
SOURCE_DIR ${FortranCInterface_SOURCE_DIR}/Verify
BINARY_DIR ${FortranCInterface_BINARY_DIR}/Verify${lang}
+ NO_CACHE
CMAKE_FLAGS -DVERIFY_CXX=${verify_cxx}
-DCMAKE_VERBOSE_MAKEFILE=ON
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
@@ -443,7 +444,6 @@
message(CHECK_FAIL "Failed")
set(FortranCInterface_VERIFIED_${lang} 0 CACHE INTERNAL "Fortran/${lang} compatibility")
endif()
- unset(FortranCInterface_VERIFY_${lang}_COMPILED CACHE)
endif()
# Error if compilers are incompatible.
diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake
index a4ee521..4f8311e 100644
--- a/Modules/FortranCInterface/Detect.cmake
+++ b/Modules/FortranCInterface/Detect.cmake
@@ -45,6 +45,7 @@
TARGET FortranCInterface
SOURCE_DIR ${FortranCInterface_SOURCE_DIR}
BINARY_DIR ${FortranCInterface_BINARY_DIR}
+ NO_CACHE
LOG_DESCRIPTION "Fortran/C interface test project"
CMAKE_FLAGS
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
@@ -54,8 +55,6 @@
${_FortranCInterface_OSX_ARCH}
${_FortranCInterface_EXE_LINKER_FLAGS}
)
-set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
-unset(FortranCInterface_COMPILED CACHE)
unset(_FortranCInterface_EXE_LINKER_FLAGS)
unset(_FortranCInterface_OSX_ARCH)
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index 992b71e..72f307f 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -174,6 +174,7 @@
[TEST_SUFFIX suffix]
[TEST_FILTER expr]
[NO_PRETTY_TYPES] [NO_PRETTY_VALUES]
+ [LIST_SEPARATOR sep]
[PROPERTIES name1 value1...]
[TEST_LIST var]
[DISCOVERY_TIMEOUT seconds]
@@ -328,6 +329,14 @@
:prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are preserved,
see policy :policy:`CMP0178`.
+ ``LIST_SEPARATOR``
+ .. versionadded:: 4.4
+
+ By default, ``PROPERTIES`` key-value pairs cannot have lists as their
+ values. By providing a non-semicolon character delimiter, it is possible to
+ pass lists as property values. Note that when doing so, the chosen character
+ cannot appear in any of the property values.
+
#]=======================================================================]
# Save project's policies
@@ -562,6 +571,7 @@
DISCOVERY_TIMEOUT
XML_OUTPUT_DIR
DISCOVERY_MODE
+ LIST_SEPARATOR
)
set(multiValueArgs
EXTRA_ARGS
@@ -589,30 +599,12 @@
set(arg_DISCOVERY_MODE ${CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE})
endif()
- get_property(
- has_counter
- TARGET ${target}
- PROPERTY CTEST_DISCOVERED_TEST_COUNTER
- SET
- )
- if(has_counter)
- get_property(
- counter
- TARGET ${target}
- PROPERTY CTEST_DISCOVERED_TEST_COUNTER
- )
- math(EXPR counter "${counter} + 1")
- else()
- set(counter 1)
- endif()
- set_property(
- TARGET ${target}
- PROPERTY CTEST_DISCOVERED_TEST_COUNTER
- ${counter}
- )
+ string(SHA256 argn_hash "${ARGN}")
+ string(SUBSTRING "${argn_hash}" 0 8 argn_hash)
+ string(MAKE_C_IDENTIFIER "${target}_${argn_hash}" ctest_file_base)
# Define rule to generate test list for aforementioned test executable
- set(ctest_file_base "${CMAKE_CURRENT_BINARY_DIR}/${target}[${counter}]")
+ set(ctest_file_base "${CMAKE_CURRENT_BINARY_DIR}/${ctest_file_base}")
set(ctest_include_file "${ctest_file_base}_include.cmake")
set(ctest_tests_file "${ctest_file_base}_tests.cmake")
get_property(test_launcher
@@ -699,6 +691,7 @@
-D "TEST_FILTER=${arg_TEST_FILTER}"
-D "NO_PRETTY_TYPES=${arg_NO_PRETTY_TYPES}"
-D "NO_PRETTY_VALUES=${arg_NO_PRETTY_VALUES}"
+ -D "LIST_SEPARATOR=${arg_LIST_SEPARATOR}"
-D "TEST_LIST=${arg_TEST_LIST}"
-D "CTEST_FILE=${ctest_tests_file}"
-D "TEST_DISCOVERY_TIMEOUT=${arg_DISCOVERY_TIMEOUT}"
diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake
index b12a336..7dacb38 100644
--- a/Modules/GoogleTestAddTests.cmake
+++ b/Modules/GoogleTestAddTests.cmake
@@ -52,7 +52,7 @@
# Handle disabled tests
set(maybe_DISABLED "")
if(pretty_test_suite MATCHES "^DISABLED_" OR pretty_test_name MATCHES "^DISABLED_")
- set(maybe_DISABLED DISABLED YES)
+ set(maybe_DISABLED "DISABLED YES")
string(REGEX REPLACE "^DISABLED_" "" pretty_test_suite "${pretty_test_suite}")
string(REGEX REPLACE "^DISABLED_" "" pretty_test_name "${pretty_test_name}")
endif()
@@ -98,6 +98,10 @@
# Add to script. Do not use add_command() here because it messes up the
# handling of empty values when forwarding arguments, and we need to
# preserve those carefully for arg_TEST_EXECUTOR and arg_EXTRA_ARGS.
+ # Test properties with values that are lists are also not handled
+ # correctly because the properties need to be expressed as a list
+ # of key-value pairs, but that list is flattened, so any values
+ # that are lists can't be differentiated from the next key.
string(APPEND script "add_test(${guarded_testname} ${launcherArgs}")
foreach(arg IN ITEMS
"${arg_TEST_EXECUTABLE}"
@@ -121,18 +125,40 @@
set(maybe_LOCATION "")
if(NOT current_test_file STREQUAL "" AND NOT current_test_line STREQUAL "")
- set(maybe_LOCATION DEF_SOURCE_LINE "${current_test_file}:${current_test_line}")
+ set(maybe_LOCATION "DEF_SOURCE_LINE [==[${current_test_file}:${current_test_line}]==]")
endif()
- add_command(set_tests_properties
- "${guarded_testname}"
- PROPERTIES
- ${maybe_DISABLED}
- ${maybe_LOCATION}
- WORKING_DIRECTORY "${arg_TEST_WORKING_DIR}"
- SKIP_REGULAR_EXPRESSION "\\[ SKIPPED \\]"
- ${arg_TEST_PROPERTIES}
+ string(APPEND script
+ "set_tests_properties(${guarded_testname}\n"
+ " PROPERTIES\n"
+ " ${maybe_DISABLED}\n"
+ " ${maybe_LOCATION}\n"
+ " WORKING_DIRECTORY [==[${arg_TEST_WORKING_DIR}]==]\n"
+ " SKIP_REGULAR_EXPRESSION [==[\\[ SKIPPED \\]]==]\n"
)
+ if(arg_TEST_PROPERTIES)
+ # Making local copy of arg_TEST_PROPERTIES, as write_test_to_file is
+ # called in a loop and we don't want to destroy the parsed arg value
+ # by POP_FRONT-ing from it.
+ set(test_properties "${arg_TEST_PROPERTIES}")
+ list(LENGTH test_properties test_properties_length)
+ math(EXPR test_properties_length_mod2 "${test_properties_length} % 2")
+ if(NOT test_properties_length_mod2 EQUAL 0)
+ message(FATAL_ERROR
+ "gtest_discover_tests() received a key-value list of properties with an uneven number of elements.\n"
+ "Check the supplied TEST_PROPERTIES argument and LIST_SEPARATOR if used."
+ )
+ endif()
+ while(NOT test_properties_length EQUAL 0)
+ list(POP_FRONT test_properties property_name property_value)
+ list(LENGTH test_properties test_properties_length)
+ if(NOT "${arg_LIST_SEPARATOR}" STREQUAL "")
+ string(REPLACE "${arg_LIST_SEPARATOR}" ";" property_value "${property_value}")
+ endif()
+ string(APPEND script " ${property_name} [==[${property_value}]==]\n")
+ endwhile()
+ endif()
+ string(APPEND script ")\n")
# possibly unbalanced square brackets render lists invalid so skip such
# tests in ${arg_TEST_LIST}
@@ -281,6 +307,7 @@
set(oneValueArgs
NO_PRETTY_TYPES # These two take a value, unlike gtest_discover_tests()
NO_PRETTY_VALUES #
+ LIST_SEPARATOR
TEST_TARGET
TEST_EXECUTABLE
TEST_WORKING_DIR
@@ -435,5 +462,6 @@
TEST_EXTRA_ARGS "${TEST_EXTRA_ARGS}"
TEST_DISCOVERY_EXTRA_ARGS "${TEST_DISCOVERY_EXTRA_ARGS}"
TEST_PROPERTIES "${TEST_PROPERTIES}"
+ LIST_SEPARATOR "${LIST_SEPARATOR}"
)
endif()
diff --git a/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake b/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake
index ea07a22..076ab1c 100644
--- a/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake
+++ b/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake
@@ -108,6 +108,7 @@
else()
string(APPEND _nvcc_log " extracted link launcher name: [${_nvcc_host_link_launcher}]\n")
find_program(_nvcc_find_host_link_launcher
+ NO_CACHE
NAMES ${_nvcc_host_link_launcher}
PATHS ${_nvcc_path} NO_DEFAULT_PATH)
find_program(_nvcc_find_host_link_launcher
@@ -119,7 +120,7 @@
string(APPEND _nvcc_log " could not find link launcher absolute path\n")
set(CMAKE_${lang}_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
endif()
- unset(_nvcc_find_host_link_launcher CACHE)
+ unset(_nvcc_find_host_link_launcher)
endif()
endif()
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 046adc2..1ebcaaa 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -14,9 +14,9 @@
set(FALLBACK_VAR_NAMES ${ARGN})
foreach(variable_name IN LISTS FALLBACK_VAR_NAMES)
- if(${variable_name})
- set(${OUTPUT_VAR_NAME} "${${variable_name}}" PARENT_SCOPE)
- break()
+ if(DEFINED ${variable_name})
+ set(${OUTPUT_VAR_NAME} "${${variable_name}}")
+ return(PROPAGATE ${OUTPUT_VAR_NAME})
endif()
endforeach()
endfunction()
@@ -29,53 +29,60 @@
string(TOLOWER "${CPACK_DEBIAN_PACKAGE_NAME}-${component}" package_name)
endif()
- set("${var}" "${package_name}" PARENT_SCOPE)
+ set(${var} "${package_name}")
+ return(PROPAGATE ${var})
endfunction()
#extract library name and version for given shared object
function(extract_so_info shared_object libname version)
- if(CPACK_READELF_EXECUTABLE)
- execute_process(COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object}"
- WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE output
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if(result EQUAL 0)
- string(REGEX MATCH "\\(?SONAME\\)?[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}")
- set(${libname} "${CMAKE_MATCH_1}" PARENT_SCOPE)
- set(${version} "${CMAKE_MATCH_2}" PARENT_SCOPE)
- else()
- message(WARNING "Error running readelf for \"${shared_object}\"")
- endif()
- else()
+ if(NOT CPACK_READELF_EXECUTABLE)
message(FATAL_ERROR "Readelf utility is not available.")
+ return()
+ endif()
+
+ execute_process(
+ COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object}"
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE output
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(result EQUAL 0)
+ string(REGEX MATCH "\\(?SONAME\\)?[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}")
+ set(${libname} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ set(${version} "${CMAKE_MATCH_2}" PARENT_SCOPE)
+ else()
+ message(WARNING "Error running readelf for \"${shared_object}\"")
endif()
endfunction()
#extract RUNPATH and RPATH for given shared object or executable
function(extract_runpath_and_rpath shared_object_or_executable runpath rpath)
- if(CPACK_READELF_EXECUTABLE)
- execute_process(COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object_or_executable}"
- WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE output
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if(result EQUAL 0)
- string(REGEX MATCH "\\(?RUNPATH\\)?[^\n]*\\[([^\n]+)\\]" found_runpath "${output}")
- string(REPLACE ":" ";" found_runpath "${CMAKE_MATCH_1}")
- list(REMOVE_DUPLICATES found_runpath)
- string(REGEX MATCH "\\(?RPATH\\)?[^\n]*\\[([^\n]+)\\]" found_rpath "${output}")
- string(REPLACE ":" ";" found_rpath "${CMAKE_MATCH_1}")
- list(REMOVE_DUPLICATES found_rpath)
- set(${runpath} "${found_runpath}" PARENT_SCOPE)
- set(${rpath} "${found_rpath}" PARENT_SCOPE)
- else()
- message(WARNING "Error running readelf for \"${shared_object_or_executable}\"")
- endif()
- else()
+ if(NOT CPACK_READELF_EXECUTABLE)
message(FATAL_ERROR "Readelf utility is not available.")
+ return()
+ endif()
+
+ execute_process(
+ COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object_or_executable}"
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE output
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(result EQUAL 0)
+ string(REGEX MATCH "\\(?RUNPATH\\)?[^\n]*\\[([^\n]+)\\]" found_runpath "${output}")
+ string(REPLACE ":" ";" found_runpath "${CMAKE_MATCH_1}")
+ list(REMOVE_DUPLICATES found_runpath)
+ string(REGEX MATCH "\\(?RPATH\\)?[^\n]*\\[([^\n]+)\\]" found_rpath "${output}")
+ string(REPLACE ":" ";" found_rpath "${CMAKE_MATCH_1}")
+ list(REMOVE_DUPLICATES found_rpath)
+ set(${runpath} "${found_runpath}" PARENT_SCOPE)
+ set(${rpath} "${found_rpath}" PARENT_SCOPE)
+ else()
+ message(WARNING "Error running readelf for \"${shared_object_or_executable}\"")
endif()
endfunction()
@@ -84,12 +91,13 @@
# NOTE: This pattern has to stay in sync with the 'prohibited_chars' variable
# defined in the C++ function `CPackGenerator::GetSanitizedDirOrFileName`!
set(prohibited_chars_pattern "[<]|[>]|[\"]|[/]|[\\]|[|]|[?]|[*]|[`]")
- if("${dirname}" MATCHES "${prohibited_chars_pattern}")
+ if(dirname MATCHES "${prohibited_chars_pattern}")
string(MD5 sanitized_dirname "${dirname}")
- set(${outvar} "${sanitized_dirname}" PARENT_SCOPE)
+ set(${outvar} "${sanitized_dirname}")
else()
- set(${outvar} "${dirname}" PARENT_SCOPE)
+ set(${outvar} "${dirname}")
endif()
+ return(PROPAGATE ${outvar})
endfunction()
#retrieve packaging directories of components the current component depends on
@@ -97,7 +105,9 @@
function(get_packaging_dirs_of_dependencies outvar)
if(CPACK_DEB_PACKAGE_COMPONENT)
if(NOT DEFINED WDIR OR NOT DEFINED _local_component_name)
- message(FATAL_ERROR "CPackDeb: Function '${CMAKE_CURRENT_FUNCTION}' not called from correct function scope!")
+ message(
+ FATAL_ERROR "CPackDeb: Function '${CMAKE_CURRENT_FUNCTION}' not called from correct function scope!"
+ )
endif()
set(result_list)
foreach(dependency_name IN LISTS CPACK_COMPONENT_${_local_component_name}_DEPENDS)
@@ -106,30 +116,28 @@
cmake_path(NORMAL_PATH dependency_packaging_dir)
list(APPEND result_list "${dependency_packaging_dir}")
endforeach()
- set(${outvar} "${result_list}" PARENT_SCOPE) # Set return variable.
+ set(${outvar} "${result_list}") # Set return variable.
else()
- set(${outvar} "" PARENT_SCOPE) # Clear return variable.
+ set(${outvar} "") # Clear return variable.
endif()
+ return(PROPAGATE ${outvar})
endfunction()
-function(cpack_deb_check_description SUMMARY LINES RESULT_VARIABLE)
- set(_result TRUE)
-
+function(cpack_deb_check_description summary lines result_variable)
# Get the summary line
- if(NOT SUMMARY MATCHES "^[^\\s].*$")
- set(_result FALSE)
- set(${RESULT_VARIABLE} ${_result} PARENT_SCOPE)
- return()
+ if(NOT summary MATCHES "^[^\\s].*$")
+ set(${result_variable} FALSE)
+ else()
+ set(${result_variable} TRUE)
+ foreach(_line IN LISTS lines)
+ if(NOT _line MATCHES "^ +[^ ]+.*$")
+ set(${result_variable} FALSE)
+ break()
+ endif()
+ endforeach()
endif()
- foreach(_line IN LISTS LINES)
- if(NOT _line MATCHES "^ +[^ ]+.*$")
- set(_result FALSE)
- break()
- endif()
- endforeach()
-
- set(${RESULT_VARIABLE} ${_result} PARENT_SCOPE)
+ return(PROPAGATE ${result_variable})
endfunction()
function(cpack_deb_format_package_description TEXT OUTPUT_VAR)
@@ -153,8 +161,8 @@
cpack_deb_check_description("${_summary}" "${_lines}" _result)
if(_result)
# Ok, no formatting required
- set(${OUTPUT_VAR} "${TEXT}" PARENT_SCOPE)
- return()
+ set(${OUTPUT_VAR} "${TEXT}")
+ return(PROPAGATE ${OUTPUT_VAR})
endif()
# Format the summary line
@@ -180,7 +188,8 @@
list(PREPEND _result "${_summary}")
list(JOIN _result "\n" _result)
string(REPLACE "${uuid}" ";" _result "${_result}")
- set(${OUTPUT_VAR} "${_result}" PARENT_SCOPE)
+ set(${OUTPUT_VAR} "${_result}")
+ return(PROPAGATE ${OUTPUT_VAR})
endfunction()
function(cpack_deb_prepare_package_vars)
@@ -190,8 +199,11 @@
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
endif()
- set(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}")
- set(DBGSYMDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}-dbgsym")
+ cmake_path(
+ APPEND CPACK_TOPLEVEL_DIRECTORY "${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}"
+ OUTPUT_VARIABLE WDIR
+ )
+ cmake_path(APPEND_STRING WDIR "-dbgsym" OUTPUT_VARIABLE DBGSYMDIR)
file(REMOVE_RECURSE "${DBGSYMDIR}")
# per component automatic discover: some of the component might not have
@@ -204,32 +216,47 @@
if(DEFINED ${_component_shlibdeps_var})
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS "${${_component_shlibdeps_var}}")
if(CPACK_DEBIAN_PACKAGE_DEBUG)
- message("CPackDeb Debug: component '${CPACK_DEB_PACKAGE_COMPONENT}' dpkg-shlibdeps set to ${CPACK_DEBIAN_PACKAGE_SHLIBDEPS}")
+ message(
+ "CPackDeb Debug: component '${CPACK_DEB_PACKAGE_COMPONENT}' dpkg-shlibdeps set to "
+ "${CPACK_DEBIAN_PACKAGE_SHLIBDEPS}"
+ )
endif()
endif()
endif()
- cpack_deb_variable_fallback("CPACK_DEBIAN_DEBUGINFO_PACKAGE"
- "CPACK_DEBIAN_${_local_component_name}_DEBUGINFO_PACKAGE"
- "CPACK_DEBIAN_DEBUGINFO_PACKAGE")
+ cpack_deb_variable_fallback(
+ CPACK_DEBIAN_DEBUGINFO_PACKAGE
+ CPACK_DEBIAN_${_local_component_name}_DEBUGINFO_PACKAGE
+ CPACK_DEBIAN_DEBUGINFO_PACKAGE
+ )
if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OR CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS OR CPACK_DEBIAN_DEBUGINFO_PACKAGE)
# Generating binary list - Get type of all install files
file(GLOB_RECURSE FILE_PATHS_ LIST_DIRECTORIES false RELATIVE "${WDIR}" "${WDIR}/*")
find_program(FILE_EXECUTABLE file)
if(NOT FILE_EXECUTABLE)
- message(FATAL_ERROR "CPackDeb: file utility is not available. CPACK_DEBIAN_PACKAGE_SHLIBDEPS and CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS options are not available.")
+ message(
+ FATAL_ERROR
+ "CPackDeb: file utility is not available. CPACK_DEBIAN_PACKAGE_SHLIBDEPS and "
+ "CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS options are not available."
+ )
endif()
# get file info so that we can determine if file is executable or not
unset(CPACK_DEB_INSTALL_FILES)
foreach(FILE_ IN LISTS FILE_PATHS_)
- execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${FILE_EXECUTABLE} "./${FILE_}"
+ execute_process(
+ COMMAND "${CMAKE_COMMAND}" -E env LC_ALL=C "${FILE_EXECUTABLE}" "./${FILE_}"
WORKING_DIRECTORY "${WDIR}"
RESULT_VARIABLE FILE_RESULT_
- OUTPUT_VARIABLE INSTALL_FILE_)
+ OUTPUT_VARIABLE INSTALL_FILE_
+ )
if(NOT FILE_RESULT_ EQUAL 0)
- message(FATAL_ERROR "CPackDeb: execution of command: '${FILE_EXECUTABLE} ./${FILE_}' failed with exit code: ${FILE_RESULT_}")
+ message(
+ FATAL_ERROR
+ "CPackDeb: execution of command: '${FILE_EXECUTABLE} ./${FILE_}' failed with "
+ "exit code: ${FILE_RESULT_}"
+ )
endif()
list(APPEND CPACK_DEB_INSTALL_FILES "${INSTALL_FILE_}")
endforeach()
@@ -265,16 +292,22 @@
message(FATAL_ERROR "debuginfo packages require the readelf tool")
endif()
- file(RELATIVE_PATH _DBGSYM_ROOT "${CPACK_TEMPORARY_DIRECTORY}" "${DBGSYMDIR}")
+ cmake_path(
+ RELATIVE_PATH DBGSYMDIR
+ BASE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ OUTPUT_VARIABLE _DBGSYM_ROOT
+ )
foreach(_FILE IN LISTS CPACK_DEB_UNSTRIPPED_FILES)
# Get the file's Build ID
- execute_process(COMMAND env LC_ALL=C ${CPACK_READELF_EXECUTABLE} -n "${_FILE}"
+ execute_process(
+ COMMAND env LC_ALL=C "${CPACK_READELF_EXECUTABLE}" -n "${_FILE}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE READELF_OUTPUT
RESULT_VARIABLE READELF_RESULT
ERROR_VARIABLE READELF_ERROR
- OUTPUT_STRIP_TRAILING_WHITESPACE )
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(NOT READELF_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: readelf: '${READELF_ERROR}';\n"
"executed command: '${CPACK_READELF_EXECUTABLE} -n ${_FILE}'")
@@ -288,38 +321,52 @@
endif()
# Split out the debug symbols from the binaries
- set(_FILE_DBGSYM ${_DBGSYM_ROOT}/usr/lib/debug/.build-id/${_BUILD_ID_START}/${_BUILD_ID_REMAINING}.debug)
- get_filename_component(_OUT_DIR "${_FILE_DBGSYM}" DIRECTORY)
+ cmake_path(
+ APPEND _DBGSYM_ROOT "usr/lib/debug/.build-id/${_BUILD_ID_START}/${_BUILD_ID_REMAINING}.debug"
+ OUTPUT_VARIABLE _FILE_DBGSYM
+ )
+ cmake_path(GET _FILE_DBGSYM PARENT_PATH _OUT_DIR)
file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/${_OUT_DIR}")
- execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}"
+ execute_process(
+ COMMAND "${CPACK_OBJCOPY_EXECUTABLE}" --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
ERROR_VARIABLE OBJCOPY_ERROR
- OUTPUT_STRIP_TRAILING_WHITESPACE )
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(NOT OBJCOPY_RESULT EQUAL 0)
- message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
- "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'")
+ message(
+ FATAL_ERROR
+ "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
+ "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'"
+ )
endif()
- execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE}
+ execute_process(
+ COMMAND "${CPACK_OBJCOPY_EXECUTABLE}" --strip-unneeded ${_FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
ERROR_VARIABLE OBJCOPY_ERROR
- OUTPUT_STRIP_TRAILING_WHITESPACE )
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
"executed command: '${CPACK_OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'")
endif()
- execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}
+ execute_process(
+ COMMAND "${CPACK_OBJCOPY_EXECUTABLE}" --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
ERROR_VARIABLE OBJCOPY_ERROR
- OUTPUT_STRIP_TRAILING_WHITESPACE )
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(NOT OBJCOPY_RESULT EQUAL 0)
- message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
- "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'")
+ message(
+ FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
+ "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'"
+ )
endif()
endforeach()
endif()
@@ -330,10 +377,12 @@
if(SHLIBDEPS_EXECUTABLE)
# Check version of the dpkg-shlibdeps tool using CPackDEB method
- execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --version
+ execute_process(
+ COMMAND "${CMAKE_COMMAND}" -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --version
OUTPUT_VARIABLE _TMP_VERSION
ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(_TMP_VERSION MATCHES "dpkg-shlibdeps version ([0-9]+\\.[0-9]+\\.[0-9]+)")
set(SHLIBDEPS_EXECUTABLE_VERSION "${CMAKE_MATCH_1}")
else()
@@ -351,17 +400,20 @@
# Create blank control file for running dpkg-shlibdeps
# There might be some other way to invoke dpkg-shlibdeps without creating this file
# but standard debian package should not have anything that can collide with this file or directory
- file(MAKE_DIRECTORY ${CPACK_TEMPORARY_DIRECTORY}/debian)
- file(WRITE ${CPACK_TEMPORARY_DIRECTORY}/debian/control "")
+ cmake_path(APPEND CPACK_TEMPORARY_DIRECTORY debian OUTPUT_VARIABLE _debian_path)
+ file(MAKE_DIRECTORY ${_debian_path})
+ file(WRITE ${_debian_path}/control "")
# Create a DEBIAN directory so that dpkg-shlibdeps can find the package dir when resolving $ORIGIN.
file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/DEBIAN")
# Add --ignore-missing-info if the tool supports it
- execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --help
+ execute_process(
+ COMMAND "${CMAKE_COMMAND}" -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --help
OUTPUT_VARIABLE _TMP_HELP
ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(_TMP_HELP MATCHES "--ignore-missing-info")
set(IGNORE_MISSING_INFO_FLAG "--ignore-missing-info")
endif()
@@ -382,15 +434,15 @@
get_packaging_dirs_of_dependencies(deps_packaging_dirs)
foreach(exe IN LISTS CPACK_DEB_BINARY_FILES)
cmake_path(GET exe PARENT_PATH exe_dir)
- extract_runpath_and_rpath(${exe} runpath rpath)
+ extract_runpath_and_rpath("${exe}" runpath rpath)
# If RUNPATH is available, RPATH will be ignored. Therefore we have to do the same here!
- if (NOT "${runpath}" STREQUAL "")
+ if(runpath)
set(selected_rpath "${runpath}")
else()
set(selected_rpath "${rpath}")
endif()
foreach(search_path IN LISTS selected_rpath)
- if ("${search_path}" MATCHES "^[$]ORIGIN" OR "${search_path}" MATCHES "^[$][{]ORIGIN[}]")
+ if(search_path MATCHES "^[$]ORIGIN" OR search_path MATCHES "^[$][{]ORIGIN[}]")
foreach(deps_pkgdir IN LISTS deps_packaging_dirs)
string(REPLACE "\$ORIGIN" "${deps_pkgdir}/${exe_dir}" path "${search_path}")
string(REPLACE "\${ORIGIN}" "${deps_pkgdir}/${exe_dir}" path "${path}")
@@ -403,44 +455,60 @@
list(REMOVE_DUPLICATES PRIVATE_SEARCH_DIR_OPTIONS)
elseif(NOT "${CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS}" STREQUAL "")
- message(WARNING "CPackDeb: dkpg-shlibdeps is too old. \"CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS\" is therefore ignored.")
+ message(
+ WARNING
+ "CPackDeb: dkpg-shlibdeps is too old. \"CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS\" "
+ "is therefore ignored."
+ )
endif()
# Execute dpkg-shlibdeps
# --ignore-missing-info : allow dpkg-shlibdeps to run even if some libs do not belong to a package
# -l<dir>: make dpkg-shlibdeps also search in this directory for (private) shared library dependencies
# -O : print to STDOUT
- execute_process(COMMAND ${SHLIBDEPS_EXECUTABLE} ${PRIVATE_SEARCH_DIR_OPTIONS} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}
+ execute_process(
+ COMMAND "${SHLIBDEPS_EXECUTABLE}" ${PRIVATE_SEARCH_DIR_OPTIONS} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE SHLIBDEPS_OUTPUT
RESULT_VARIABLE SHLIBDEPS_RESULT
ERROR_VARIABLE SHLIBDEPS_ERROR
- OUTPUT_STRIP_TRAILING_WHITESPACE )
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
# E2K OSL 6.0.1 and prior has broken dpkg-shlibdeps. CPack will deal with that (mocking SHLIBDEPS_OUTPUT), but inform user of this.
- if("${SHLIBDEPS_ERROR}" MATCHES "unknown gcc system type e2k.*, falling back to default")
- message(WARNING "CPackDeb: broken dpkg-shlibdeps on E2K detected, will fall back to minimal dependencies.\n"
- "You should expect that dependencies list in the package will be incomplete.")
+ if(SHLIBDEPS_ERROR MATCHES "unknown gcc system type e2k.*, falling back to default")
+ message(
+ WARNING
+ "CPackDeb: broken dpkg-shlibdeps on E2K detected, will fall back to minimal dependencies.\n"
+ "You should expect that dependencies list in the package will be incomplete."
+ )
set(SHLIBDEPS_OUTPUT "shlibs:Depends=libc6, lcc-libs")
endif()
if(CPACK_DEBIAN_PACKAGE_DEBUG)
# dpkg-shlibdeps will throw some warnings if some input files are not binary
- message( "CPackDeb Debug: dpkg-shlibdeps warnings \n${SHLIBDEPS_ERROR}")
+ message("CPackDeb Debug: dpkg-shlibdeps warnings \n${SHLIBDEPS_ERROR}")
endif()
if(NOT SHLIBDEPS_RESULT EQUAL 0)
- message(FATAL_ERROR "CPackDeb: dpkg-shlibdeps: '${SHLIBDEPS_ERROR}';\n"
- "executed command: '${SHLIBDEPS_EXECUTABLE} ${PRIVATE_SEARCH_DIR_OPTIONS} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}';\n"
- "found files: '${INSTALL_FILE_}';\n"
- "files info: '${CPACK_DEB_INSTALL_FILES}';\n"
- "binary files: '${CPACK_DEB_BINARY_FILES}'")
+ message(
+ FATAL_ERROR
+ "CPackDeb: dpkg-shlibdeps: '${SHLIBDEPS_ERROR}';\n"
+ "executed command: '${SHLIBDEPS_EXECUTABLE} ${PRIVATE_SEARCH_DIR_OPTIONS} "
+ "${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}';\n"
+ "found files: '${INSTALL_FILE_}';\n"
+ "files info: '${CPACK_DEB_INSTALL_FILES}';\n"
+ "binary files: '${CPACK_DEB_BINARY_FILES}'"
+ )
endif()
#Get rid of prefix generated by dpkg-shlibdeps
string(REGEX REPLACE "^.*Depends=" "" CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS "${SHLIBDEPS_OUTPUT}")
if(CPACK_DEBIAN_PACKAGE_DEBUG)
- message("CPackDeb Debug: Found dependency: ${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS} from output ${SHLIBDEPS_OUTPUT}")
+ message("
+ CPackDeb Debug: Found dependency: ${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS} from "
+ "output ${SHLIBDEPS_OUTPUT}"
+ )
endif()
# Remove blank control file
@@ -451,11 +519,17 @@
file(REMOVE_RECURSE "${CPACK_TEMPORARY_DIRECTORY}/DEBIAN")
else()
if(CPACK_DEBIAN_PACKAGE_DEBUG)
- message(AUTHOR_WARNING "CPackDeb Debug: Using only user-provided depends because package does not contain executable files that link to shared libraries.")
+ message(
+ AUTHOR_WARNING
+ "CPackDeb Debug: Using only user-provided depends because package does not "
+ "contain executable files that link to shared libraries."
+ )
endif()
endif()
else()
- message("CPackDeb: Using only user-provided dependencies because dpkg-shlibdeps is not found.")
+ message(
+ "CPackDeb: Using only user-provided dependencies because dpkg-shlibdeps is not found."
+ )
endif()
else()
@@ -515,8 +589,11 @@
# CMake 3.10 did not check for version format so we have to preserve
# backward compatibility
if(CPACK_DEBIAN_PACKAGE_VERSION MATCHES ".*-.*")
- message(FATAL_ERROR
- "CPackDeb: Debian package version must not contain hyphens when CPACK_DEBIAN_PACKAGE_RELEASE is not provided!")
+ message(
+ FATAL_ERROR
+ "CPackDeb: Debian package version must not contain hyphens when "
+ "CPACK_DEBIAN_PACKAGE_RELEASE is not provided!"
+ )
endif()
endif()
@@ -535,15 +612,16 @@
elseif(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
# There is no such thing as i686 architecture on debian, you should use i386 instead
# $ dpkg --print-architecture
- find_program(DPKG_CMD dpkg)
- if(NOT DPKG_CMD)
+ find_program(DPKG_EXECUTABLE dpkg)
+ if(NOT DPKG_EXECUTABLE)
message(STATUS "CPackDeb: Can not find dpkg in your path, default to i386.")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
endif()
- execute_process(COMMAND "${DPKG_CMD}" --print-architecture
+ execute_process(
+ COMMAND "${DPKG_EXECUTABLE}" --print-architecture
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
OUTPUT_STRIP_TRAILING_WHITESPACE
- )
+ )
endif()
# Source: (optional)
@@ -564,7 +642,13 @@
# if per-component variable, overrides the global CPACK_DEBIAN_PACKAGE_${variable_type_}
# automatic dependency discovery will be performed afterwards.
if(CPACK_DEB_PACKAGE_COMPONENT)
- foreach(value_type_ IN ITEMS DEPENDS RECOMMENDS SUGGESTS PREDEPENDS ENHANCES BREAKS CONFLICTS PROVIDES REPLACES MULTIARCH SOURCE SECTION PRIORITY NAME)
+ set(
+ _value_types
+ DEPENDS RECOMMENDS SUGGESTS PREDEPENDS ENHANCES BREAKS
+ CONFLICTS PROVIDES REPLACES MULTIARCH SOURCE SECTION
+ PRIORITY NAME
+ )
+ foreach(value_type_ IN LISTS _value_types)
set(_component_var "CPACK_DEBIAN_${_local_component_name}_PACKAGE_${value_type_}")
# if set, overrides the global variable
@@ -605,7 +689,11 @@
# Maintainer: (mandatory)
if(NOT CPACK_DEBIAN_PACKAGE_MAINTAINER)
if(NOT CPACK_PACKAGE_CONTACT)
- message(FATAL_ERROR "CPackDeb: Debian package requires a maintainer for a package, set CPACK_PACKAGE_CONTACT or CPACK_DEBIAN_PACKAGE_MAINTAINER")
+ message(
+ FATAL_ERROR
+ "CPackDeb: Debian package requires a maintainer for a package, set "
+ "CPACK_PACKAGE_CONTACT or CPACK_DEBIAN_PACKAGE_MAINTAINER"
+ )
endif()
set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT})
endif()
@@ -618,13 +706,17 @@
set(_desc_fallback "CPACK_PACKAGE_DESCRIPTION")
endif()
if(CPACK_DEB_PACKAGE_COMPONENT)
- cpack_deb_variable_fallback("CPACK_DEBIAN_PACKAGE_DESCRIPTION"
- "CPACK_DEBIAN_${_local_component_name}_DESCRIPTION"
- "CPACK_COMPONENT_${_local_component_name}_DESCRIPTION")
+ cpack_deb_variable_fallback(
+ CPACK_DEBIAN_PACKAGE_DESCRIPTION
+ CPACK_DEBIAN_${_local_component_name}_DESCRIPTION
+ CPACK_COMPONENT_${_local_component_name}_DESCRIPTION
+ )
else()
- cpack_deb_variable_fallback("CPACK_DEBIAN_PACKAGE_DESCRIPTION"
- "CPACK_DEBIAN_PACKAGE_DESCRIPTION"
- ${_desc_fallback})
+ cpack_deb_variable_fallback(
+ CPACK_DEBIAN_PACKAGE_DESCRIPTION
+ CPACK_DEBIAN_PACKAGE_DESCRIPTION
+ ${_desc_fallback}
+ )
endif()
# Still no description? ... and description file has set ...
@@ -643,7 +735,8 @@
else()
# Giving up! Report an error...
set(_description_failure_message
- "CPackDeb: Debian package requires a summary for a package, set CPACK_PACKAGE_DESCRIPTION_SUMMARY or CPACK_DEBIAN_PACKAGE_DESCRIPTION")
+ "CPackDeb: Debian package requires a summary for a package, set "
+ "CPACK_PACKAGE_DESCRIPTION_SUMMARY or CPACK_DEBIAN_PACKAGE_DESCRIPTION")
if(CPACK_DEB_PACKAGE_COMPONENT)
string(APPEND _description_failure_message
" or CPACK_DEBIAN_${_local_component_name}_DESCRIPTION")
@@ -684,12 +777,16 @@
if(CPACK_DEBIAN_ARCHIVE_TYPE)
if(CPACK_DEBIAN_ARCHIVE_TYPE STREQUAL "paxr")
- message(DEPRECATION "CPACK_DEBIAN_ARCHIVE_TYPE set to old and invalid "
- "type 'paxr', mapping to 'gnutar'")
+ message(
+ DEPRECATION
+ "CPACK_DEBIAN_ARCHIVE_TYPE set to old and invalid type 'paxr', mapping to 'gnutar'"
+ )
set(CPACK_DEBIAN_ARCHIVE_TYPE "gnutar")
elseif(NOT CPACK_DEBIAN_ARCHIVE_TYPE STREQUAL "gnutar")
- message(FATAL_ERROR "CPACK_DEBIAN_ARCHIVE_TYPE set to unsupported"
- "type ${CPACK_DEBIAN_ARCHIVE_TYPE}")
+ message(
+ FATAL_ERROR
+ "CPACK_DEBIAN_ARCHIVE_TYPE set to unsupported type ${CPACK_DEBIAN_ARCHIVE_TYPE}"
+ )
endif()
else()
set(CPACK_DEBIAN_ARCHIVE_TYPE "gnutar")
@@ -739,58 +836,106 @@
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
extract_so_info("${_FILE}" libname soversion)
if(libname AND DEFINED soversion)
- list(APPEND CPACK_DEBIAN_PACKAGE_SHLIBS_LIST
- "${libname} ${soversion} ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY} ${CPACK_DEBIAN_PACKAGE_VERSION})")
+ list(
+ APPEND CPACK_DEBIAN_PACKAGE_SHLIBS_LIST
+ "${libname} ${soversion} ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY} ${CPACK_DEBIAN_PACKAGE_VERSION})"
+ )
else()
- message(AUTHOR_WARNING "Shared library '${_FILE}' is missing soname or soversion. Library will not be added to DEBIAN/shlibs control file.")
+ message(
+ AUTHOR_WARNING
+ "Shared library '${_FILE}' is missing soname or soversion. "
+ "Library will not be added to DEBIAN/shlibs control file."
+ )
endif()
endforeach()
list(JOIN CPACK_DEBIAN_PACKAGE_SHLIBS_LIST "\n" CPACK_DEBIAN_PACKAGE_SHLIBS_LIST)
else()
- message(FATAL_ERROR "Readelf utility is not available. CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS option is not available.")
+ message(
+ FATAL_ERROR
+ "Readelf utility is not available. CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS option is not available."
+ )
endif()
endif()
# add ldconfig call in default postrm and postint
- set(CPACK_ADD_LDCONFIG_CALL 0)
+ set(_PACKAGE_HAS_SHARED_LIBS 0)
# all files in CPACK_DEB_SHARED_OBJECT_FILES have dot at the beginning
set(_LDCONF_DEFAULTS "./lib" "./usr/lib")
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
- get_filename_component(_DIR ${_FILE} DIRECTORY)
- get_filename_component(_PARENT_DIR ${_DIR} DIRECTORY)
+ cmake_path(GET _FILE PARENT_PATH _DIR)
+ cmake_path(GET _DIR PARENT_PATH _PARENT_DIR)
if(_DIR IN_LIST _LDCONF_DEFAULTS OR _PARENT_DIR IN_LIST _LDCONF_DEFAULTS)
- set(CPACK_ADD_LDCONFIG_CALL 1)
+ set(_PACKAGE_HAS_SHARED_LIBS 1)
endif()
endforeach()
- if(CPACK_ADD_LDCONFIG_CALL)
- set(CPACK_DEBIAN_GENERATE_POSTINST 1)
- set(CPACK_DEBIAN_GENERATE_POSTRM 1)
- foreach(f IN LISTS CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA)
- get_filename_component(n "${f}" NAME)
- if(n STREQUAL "postinst")
+ if(_PACKAGE_HAS_SHARED_LIBS)
+ # Expecting a modern distro to generate `debian/triggers` instead
+ # of legacy `ldconfig` calls from postinst/postrm
+ set(_dpkg_is_old FALSE)
+ if(DPKG_EXECUTABLE)
+ execute_process(
+ COMMAND "${DPKG_EXECUTABLE}" --version
+ OUTPUT_VARIABLE DPKG_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ set(_dpkg_version_re "Debian 'dpkg' package management program version ([0-9]+\.[0-9]+\.[0-9]+).*")
+ if(DPKG_VERSION MATCHES "${_dpkg_version_re}")
+ set(DPKG_VERSION "${CMAKE_MATCH_1}")
+ if(DPKG_VERSION VERSION_LESS 1.18.3)
+ set(_dpkg_is_old TRUE)
+ endif()
+ else()
+ set(_dpkg_is_old TRUE)
+ endif()
+ else()
+ set(_dpkg_is_old TRUE)
+ endif()
+ if(_dpkg_is_old)
+ set(CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS 0)
+ set(CPACK_DEBIAN_GENERATE_POSTINST 1)
+ set(CPACK_DEBIAN_GENERATE_POSTRM 1)
+ message(STATUS "CPackDeb: Providing legacy postinst/postrm.")
+ else()
+ set(CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS 1)
+ set(CPACK_DEBIAN_GENERATE_POSTINST 0)
+ set(CPACK_DEBIAN_GENERATE_POSTRM 0)
+ endif()
+ foreach(control_file IN LISTS CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA)
+ cmake_path(GET control_file FILENAME name)
+ if(name STREQUAL "postinst")
set(CPACK_DEBIAN_GENERATE_POSTINST 0)
endif()
- if(n STREQUAL "postrm")
+ if(name STREQUAL "postrm")
set(CPACK_DEBIAN_GENERATE_POSTRM 0)
endif()
+ if(name STREQUAL "triggers")
+ set(CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS 0)
+ endif()
endforeach()
else()
+ set(CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS 0)
set(CPACK_DEBIAN_GENERATE_POSTINST 0)
set(CPACK_DEBIAN_GENERATE_POSTRM 0)
endif()
- cpack_deb_variable_fallback("CPACK_DEBIAN_FILE_NAME"
- "CPACK_DEBIAN_${_local_component_name}_FILE_NAME"
- "CPACK_DEBIAN_FILE_NAME")
+ cpack_deb_variable_fallback(
+ CPACK_DEBIAN_FILE_NAME
+ CPACK_DEBIAN_${_local_component_name}_FILE_NAME
+ CPACK_DEBIAN_FILE_NAME
+ )
if(CPACK_DEBIAN_FILE_NAME)
if(CPACK_DEBIAN_FILE_NAME STREQUAL "DEB-DEFAULT")
# Patch package file name to be in correct debian format:
# <foo>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
- set(CPACK_OUTPUT_FILE_NAME
- "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
- set(CPACK_DBGSYM_OUTPUT_FILE_NAME
- "${CPACK_DEBIAN_PACKAGE_NAME}-dbgsym_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.ddeb")
+ set(
+ CPACK_OUTPUT_FILE_NAME
+ "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb"
+ )
+ set(
+ CPACK_DBGSYM_OUTPUT_FILE_NAME
+ "${CPACK_DEBIAN_PACKAGE_NAME}-dbgsym_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.ddeb"
+ )
else()
if(NOT CPACK_DEBIAN_FILE_NAME MATCHES ".*\\.(deb|ipk)")
set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.deb")
@@ -800,9 +945,12 @@
string(REGEX REPLACE "\.deb$" "-dbgsym.ddeb" CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}")
endif()
- set(CPACK_TEMPORARY_PACKAGE_FILE_NAME "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_OUTPUT_FILE_NAME}")
- get_filename_component(BINARY_DIR "${CPACK_OUTPUT_FILE_PATH}" DIRECTORY)
- set(CPACK_OUTPUT_FILE_PATH "${BINARY_DIR}/${CPACK_OUTPUT_FILE_NAME}")
+ cmake_path(
+ APPEND CPACK_TOPLEVEL_DIRECTORY "${CPACK_OUTPUT_FILE_NAME}"
+ OUTPUT_VARIABLE CPACK_TEMPORARY_PACKAGE_FILE_NAME
+ )
+ cmake_path(GET CPACK_OUTPUT_FILE_PATH PARENT_PATH BINARY_DIR)
+ cmake_path(APPEND BINARY_DIR "${CPACK_OUTPUT_FILE_NAME}" OUTPUT_VARIABLE CPACK_OUTPUT_FILE_PATH)
else()
# back compatibility - don't change the name
string(REGEX REPLACE "\.deb$" "-dbgsym.ddeb" CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}")
@@ -876,6 +1024,8 @@
"${CPACK_DEBIAN_PACKAGE_SOURCE}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_GENERATE_POSTINST "${CPACK_DEBIAN_GENERATE_POSTINST}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_GENERATE_POSTRM "${CPACK_DEBIAN_GENERATE_POSTRM}" PARENT_SCOPE)
+ set(GEN_CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS
+ "${CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS}" PARENT_SCOPE)
set(GEN_WDIR "${WDIR}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE "${CPACK_DEBIAN_DEBUGINFO_PACKAGE}" PARENT_SCOPE)
diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake
index d0454e1..75b3b40 100644
--- a/Modules/Internal/CPack/CPackRPM.cmake
+++ b/Modules/Internal/CPack/CPackRPM.cmake
@@ -21,32 +21,32 @@
# on shell
set_spec_script_if_enabled(
- "post"
+ post
"${PACKAGE_NAME}"
"${RPM_SYMLINK_POSTINSTALL}\n${CPACK_RPM_SPEC_POSTINSTALL}")
set_spec_script_if_enabled(
- "posttrans"
+ posttrans
"${PACKAGE_NAME}"
"${CPACK_RPM_SPEC_POSTTRANS}")
set_spec_script_if_enabled(
- "postun"
+ postun
"${PACKAGE_NAME}"
"${CPACK_RPM_SPEC_POSTUNINSTALL}")
set_spec_script_if_enabled(
- "pre"
+ pre
"${PACKAGE_NAME}"
"${CPACK_RPM_SPEC_PREINSTALL}")
set_spec_script_if_enabled(
- "pretrans"
+ pretrans
"${PACKAGE_NAME}"
"${CPACK_RPM_SPEC_PRETRANS}")
set_spec_script_if_enabled(
- "preun"
+ preun
"${PACKAGE_NAME}"
"${CPACK_RPM_SPEC_PREUNINSTALL}")
endmacro()
@@ -54,38 +54,40 @@
function(make_rpm_spec_path var path)
# RPM supports either whitespace with quoting or globbing without quoting.
if(path MATCHES "[ \t]")
- set("${var}" "\"${path}\"" PARENT_SCOPE)
+ set(${var} "\"${path}\"")
else()
- set("${var}" "${path}" PARENT_SCOPE)
+ set(${var} "${path}")
endif()
+ return(PROPAGATE ${var})
endfunction()
function(get_file_permissions FILE RETURN_VAR)
- execute_process(COMMAND ls -l ${FILE}
- OUTPUT_VARIABLE permissions_
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(
+ COMMAND stat --format=%A "${FILE}"
+ OUTPUT_VARIABLE permissions_str
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
- string(REPLACE " " ";" permissions_ "${permissions_}")
- list(GET permissions_ 0 permissions_)
+ string(REGEX REPLACE "(.)" "\\1;" permissions "${permissions_str}")
+ list(POP_FRONT permissions _) # drop the very first char (entry type)
- unset(text_notation_)
- set(any_chars_ ".")
- foreach(PERMISSION_TYPE "OWNER" "GROUP" "WORLD")
- if(permissions_ MATCHES "${any_chars_}r.*")
- list(APPEND text_notation_ "${PERMISSION_TYPE}_READ")
+ unset(result)
+ foreach(PERMISSION_TYPE IN ITEMS OWNER GROUP WORLD)
+ list(POP_FRONT permissions r_ w_ x_)
+ if(r_ STREQUAL "r")
+ list(APPEND result ${PERMISSION_TYPE}_READ)
endif()
- string(APPEND any_chars_ ".")
- if(permissions_ MATCHES "${any_chars_}w.*")
- list(APPEND text_notation_ "${PERMISSION_TYPE}_WRITE")
+ if(w_ STREQUAL "w")
+ list(APPEND result ${PERMISSION_TYPE}_WRITE)
endif()
- string(APPEND any_chars_ ".")
- if(permissions_ MATCHES "${any_chars_}x.*")
- list(APPEND text_notation_ "${PERMISSION_TYPE}_EXECUTE")
+ if(x_ STREQUAL "x")
+ list(APPEND result ${PERMISSION_TYPE}_EXECUTE)
endif()
endforeach()
- set(${RETURN_VAR} "${text_notation_}" PARENT_SCOPE)
+ set(${RETURN_VAR} "${result}")
+ return(PROPAGATE ${RETURN_VAR})
endfunction()
function(get_unix_permissions_octal_notation PERMISSIONS_VAR RETURN_VAR)
@@ -98,15 +100,15 @@
message(FATAL_ERROR "${PERMISSIONS_VAR} contains duplicate values.")
endif()
- foreach(PERMISSION_TYPE "OWNER" "GROUP" "WORLD")
+ foreach(PERMISSION_TYPE IN ITEMS OWNER GROUP WORLD)
set(${PERMISSION_TYPE}_PERMISSIONS 0)
- foreach(PERMISSION ${PERMISSIONS})
- if("${PERMISSION}" STREQUAL "${PERMISSION_TYPE}_READ")
+ foreach(PERMISSION IN LISTS PERMISSIONS)
+ if(PERMISSION STREQUAL "${PERMISSION_TYPE}_READ")
math(EXPR ${PERMISSION_TYPE}_PERMISSIONS "${${PERMISSION_TYPE}_PERMISSIONS} + 4")
- elseif("${PERMISSION}" STREQUAL "${PERMISSION_TYPE}_WRITE")
+ elseif(PERMISSION STREQUAL "${PERMISSION_TYPE}_WRITE")
math(EXPR ${PERMISSION_TYPE}_PERMISSIONS "${${PERMISSION_TYPE}_PERMISSIONS} + 2")
- elseif("${PERMISSION}" STREQUAL "${PERMISSION_TYPE}_EXECUTE")
+ elseif(PERMISSION STREQUAL "${PERMISSION_TYPE}_EXECUTE")
math(EXPR ${PERMISSION_TYPE}_PERMISSIONS "${${PERMISSION_TYPE}_PERMISSIONS} + 1")
elseif(PERMISSION MATCHES "${PERMISSION_TYPE}.*")
message(FATAL_ERROR "${PERMISSIONS_VAR} contains invalid values.")
@@ -114,22 +116,24 @@
endforeach()
endforeach()
- set(${RETURN_VAR} "${OWNER_PERMISSIONS}${GROUP_PERMISSIONS}${WORLD_PERMISSIONS}" PARENT_SCOPE)
-endfunction()
-
-function(cpack_rpm_exact_regex regex_var string)
- string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex "${string}")
- set("${regex_var}" "${regex}" PARENT_SCOPE)
+ set(${RETURN_VAR} "${OWNER_PERMISSIONS}${GROUP_PERMISSIONS}${WORLD_PERMISSIONS}")
+ return(PROPAGATE ${RETURN_VAR})
endfunction()
function(cpack_rpm_prepare_relocation_paths)
# set appropriate prefix, remove possible trailing slash and convert backslashes to slashes
if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX)
- file(TO_CMAKE_PATH "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX}" PATH_PREFIX)
+ cmake_path(
+ CONVERT "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX}"
+ TO_CMAKE_PATH_LIST PATH_PREFIX NORMALIZE
+ )
elseif(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_PREFIX)
- file(TO_CMAKE_PATH "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_PREFIX}" PATH_PREFIX)
+ cmake_path(
+ CONVERT "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_PREFIX}"
+ TO_CMAKE_PATH_LIST PATH_PREFIX NORMALIZE
+ )
else()
- file(TO_CMAKE_PATH "${CPACK_PACKAGING_INSTALL_PREFIX}" PATH_PREFIX)
+ cmake_path(CONVERT "${CPACK_PACKAGING_INSTALL_PREFIX}" TO_CMAKE_PATH_LIST PATH_PREFIX NORMALIZE )
endif()
set(RPM_RELOCATION_PATHS "${CPACK_RPM_RELOCATION_PATHS}")
@@ -150,24 +154,19 @@
endif()
# set other path prefixes
- foreach(RELOCATION_PATH ${RPM_RELOCATION_PATHS})
+ foreach(RELOCATION_PATH IN LISTS RPM_RELOCATION_PATHS)
if(IS_ABSOLUTE "${RELOCATION_PATH}")
set(PREPARED_RELOCATION_PATH "${RELOCATION_PATH}")
- elseif(PATH_PREFIX STREQUAL "/")
- # don't prefix path with a second slash as "//" is treated as network path
- # by get_filename_component() so it remains in path even inside rpm
- # package where it may cause problems with relocation
- set(PREPARED_RELOCATION_PATH "/${RELOCATION_PATH}")
else()
set(PREPARED_RELOCATION_PATH "${PATH_PREFIX}/${RELOCATION_PATH}")
endif()
# handle cases where path contains extra slashes (e.g. /a//b/ instead of
# /a/b)
- get_filename_component(PREPARED_RELOCATION_PATH
- "${PREPARED_RELOCATION_PATH}" ABSOLUTE)
+ cmake_path(ABSOLUTE_PATH PREPARED_RELOCATION_PATH NORMALIZE)
if(EXISTS "${WDIR}/${PREPARED_RELOCATION_PATH}")
+ string(REGEX REPLACE "/*$" "" PREPARED_RELOCATION_PATH "${PREPARED_RELOCATION_PATH}")
string(APPEND TMP_RPM_PREFIXES "Prefix: ${PREPARED_RELOCATION_PATH}\n")
list(APPEND RPM_USED_PACKAGE_PREFIXES "${PREPARED_RELOCATION_PATH}")
endif()
@@ -175,35 +174,36 @@
# warn about all the paths that are not relocatable
file(GLOB_RECURSE FILE_PATHS_ "${WDIR}/*")
- foreach(TMP_PATH ${FILE_PATHS_})
+ foreach(TMP_PATH IN LISTS FILE_PATHS_)
string(LENGTH "${WDIR}" WDIR_LEN)
string(SUBSTRING "${TMP_PATH}" ${WDIR_LEN} -1 TMP_PATH)
unset(TMP_PATH_FOUND_)
- foreach(RELOCATION_PATH ${RPM_USED_PACKAGE_PREFIXES})
- file(RELATIVE_PATH REL_PATH_ "${RELOCATION_PATH}" "${TMP_PATH}")
+ foreach(RELOCATION_PATH IN LISTS RPM_USED_PACKAGE_PREFIXES)
+ cmake_path(RELATIVE_PATH TMP_PATH BASE_DIRECTORY "${RELOCATION_PATH}" OUTPUT_VARIABLE REL_PATH_)
string(SUBSTRING "${REL_PATH_}" 0 2 PREFIX_)
- if(NOT "${PREFIX_}" STREQUAL "..")
+ if(NOT PREFIX_ STREQUAL "..")
set(TMP_PATH_FOUND_ TRUE)
break()
endif()
endforeach()
if(NOT TMP_PATH_FOUND_)
- message(AUTHOR_WARNING "CPackRPM:Warning: Path ${TMP_PATH} is not on one of the relocatable paths! Package will be partially relocatable.")
+ message(
+ AUTHOR_WARNING
+ "CPackRPM:Warning: Path ${TMP_PATH} is not on one of the relocatable paths! "
+ "Package will be partially relocatable."
+ )
endif()
endforeach()
-
- set(RPM_USED_PACKAGE_PREFIXES "${RPM_USED_PACKAGE_PREFIXES}" PARENT_SCOPE)
- set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}" PARENT_SCOPE)
+ return(PROPAGATE RPM_USED_PACKAGE_PREFIXES TMP_RPM_PREFIXES)
endfunction()
function(cpack_rpm_prepare_content_list)
# get files list
file(GLOB_RECURSE CPACK_RPM_INSTALL_FILES LIST_DIRECTORIES true RELATIVE "${WDIR}" "${WDIR}/*")
- set(CPACK_RPM_INSTALL_FILES "/${CPACK_RPM_INSTALL_FILES}")
- string(REPLACE ";" ";/" CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}")
+ list(TRANSFORM CPACK_RPM_INSTALL_FILES PREPEND "/")
# if we are creating a relocatable package, omit parent directories of
# CPACK_RPM_PACKAGE_PREFIX. This is achieved by building a "filter list"
@@ -214,8 +214,8 @@
# final element (so the install-prefix dir itself is not omitted
# from the RPM's content-list)
list(SORT RPM_USED_PACKAGE_PREFIXES)
- set(_DISTINCT_PATH "NOT_SET")
- foreach(_RPM_RELOCATION_PREFIX ${RPM_USED_PACKAGE_PREFIXES})
+ set(_DISTINCT_PATH NOT_SET)
+ foreach(_RPM_RELOCATION_PREFIX IN LISTS RPM_USED_PACKAGE_PREFIXES)
if(NOT "${_RPM_RELOCATION_PREFIX}" MATCHES "${_DISTINCT_PATH}/.*")
set(_DISTINCT_PATH "${_RPM_RELOCATION_PREFIX}")
@@ -223,9 +223,9 @@
list(REMOVE_AT _CPACK_RPM_PACKAGE_PREFIX_ELEMS -1)
unset(_TMP_LIST)
# Now generate all of the parent dirs of the relocation path
- foreach(_PREFIX_PATH_ELEM ${_CPACK_RPM_PACKAGE_PREFIX_ELEMS})
+ foreach(_PREFIX_PATH_ELEM IN LISTS _CPACK_RPM_PACKAGE_PREFIX_ELEMS)
list(APPEND _TMP_LIST "${_PREFIX_PATH_ELEM}")
- string(REPLACE ";" "/" _OMIT_DIR "${_TMP_LIST}")
+ list(JOIN _TMP_LIST "/" _OMIT_DIR)
separate_arguments(_OMIT_DIR)
list(APPEND _RPM_DIRS_TO_OMIT ${_OMIT_DIR})
endforeach()
@@ -298,18 +298,18 @@
endforeach()
endforeach()
- set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}" PARENT_SCOPE)
+ return(PROPAGATE CPACK_RPM_INSTALL_FILES)
endfunction()
function(cpack_rpm_symlink_get_relocation_prefixes LOCATION PACKAGE_PREFIXES RETURN_VARIABLE)
+ unset(${RETURN_VARIABLE})
foreach(PKG_PREFIX IN LISTS PACKAGE_PREFIXES)
- string(REGEX MATCH "^${PKG_PREFIX}/.*" FOUND_ "${LOCATION}")
- if(FOUND_)
- list(APPEND TMP_PREFIXES "${PKG_PREFIX}")
+ if(LOCATION MATCHES "^${PKG_PREFIX}/.*")
+ list(APPEND ${RETURN_VARIABLE} "${PKG_PREFIX}")
endif()
endforeach()
- set(${RETURN_VARIABLE} "${TMP_PREFIXES}" PARENT_SCOPE)
+ return(PROPAGATE ${RETURN_VARIABLE})
endfunction()
function(cpack_rpm_symlink_create_relocation_script PACKAGE_PREFIXES)
@@ -334,7 +334,7 @@
string(LENGTH "${POINT_PATH}" POINT_PATH_LEN)
if(_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX})
- if("${SYMLINK_INDEX}" EQUAL "${POINT_INDEX}")
+ if(SYMLINK_INDEX EQUAL POINT_INDEX)
set(INDENT "")
else()
string(APPEND SCRIPT_PART " if [ \"$RPM_INSTALL_PREFIX${POINT_INDEX}\" != \"${POINT_PATH}\" ]; then\n")
@@ -354,13 +354,16 @@
math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1+${POINT_PATH_LEN})
string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_)
- string(APPEND SCRIPT_PART " ${INDENT}if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n")
- string(APPEND SCRIPT_PART " ${INDENT}ln -s \"$RPM_INSTALL_PREFIX${POINT_INDEX}${POINT_}\" \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}${SYMLINK_}\"\n")
- string(APPEND SCRIPT_PART " ${INDENT}CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n")
- string(APPEND SCRIPT_PART " ${INDENT}fi\n")
+ string(
+ APPEND SCRIPT_PART
+ " ${INDENT}if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n"
+ " ${INDENT}ln -s \"$RPM_INSTALL_PREFIX${POINT_INDEX}${POINT_}\" \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}${SYMLINK_}\"\n"
+ " ${INDENT}CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n"
+ " ${INDENT}fi\n"
+ )
endforeach()
- if(NOT "${SYMLINK_INDEX}" EQUAL "${POINT_INDEX}")
+ if(NOT SYMLINK_INDEX EQUAL POINT_INDEX)
string(APPEND SCRIPT_PART " fi\n")
endif()
endif()
@@ -381,10 +384,13 @@
math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1)
string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_)
- string(APPEND SCRIPT_PART " if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n")
- string(APPEND SCRIPT_PART " ln -s \"${POINT_}\" \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}${SYMLINK_}\"\n")
- string(APPEND SCRIPT_PART " CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n")
- string(APPEND SCRIPT_PART " fi\n")
+ string(
+ APPEND SCRIPT_PART
+ " if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n"
+ " ln -s \"${POINT_}\" \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}${SYMLINK_}\"\n"
+ " CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n"
+ " fi\n"
+ )
endforeach()
endif()
@@ -413,10 +419,13 @@
math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1+${POINT_PATH_LEN})
string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_)
- string(APPEND SCRIPT " if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n")
- string(APPEND SCRIPT " ln -s \"$RPM_INSTALL_PREFIX${POINT_INDEX}${POINT_}\" \"${SYMLINK_}\"\n")
- string(APPEND SCRIPT " CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n")
- string(APPEND SCRIPT " fi\n")
+ string(
+ APPEND SCRIPT
+ " if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n"
+ " ln -s \"$RPM_INSTALL_PREFIX${POINT_INDEX}${POINT_}\" \"${SYMLINK_}\"\n"
+ " CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n"
+ " fi\n"
+ )
endforeach()
string(APPEND SCRIPT "fi\n")
@@ -435,13 +444,17 @@
math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1)
string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_)
- string(APPEND SCRIPT "if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n")
- string(APPEND SCRIPT " ln -s \"${POINT_}\" \"${SYMLINK_}\"\n")
- string(APPEND SCRIPT "fi\n")
+ string(
+ APPEND SCRIPT
+ "if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n"
+ " ln -s \"${POINT_}\" \"${SYMLINK_}\"\n"
+ "fi\n"
+ )
endforeach()
endif()
- set(RPM_SYMLINK_POSTINSTALL "${SCRIPT}" PARENT_SCOPE)
+ set(RPM_SYMLINK_POSTINSTALL "${SCRIPT}")
+ return(PROPAGATE RPM_SYMLINK_POSTINSTALL)
endfunction()
function(cpack_rpm_symlink_add_for_relocation_script PACKAGE_PREFIXES SYMLINK SYMLINK_RELOCATION_PATHS POINT POINT_RELOCATION_PATHS)
@@ -457,18 +470,18 @@
# source path relocated
list(APPEND _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X "${PAIR_NO}")
- list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X")
+ list(APPEND RELOCATION_VARS _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X)
foreach(POINT_RELOC_PATH IN LISTS POINT_RELOCATION_PATHS)
list(FIND PACKAGE_PREFIXES "${POINT_RELOC_PATH}" POINT_INDEX)
# both paths relocated
- list(APPEND _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX} "${PAIR_NO}")
- list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX}")
+ list(APPEND _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX} ${PAIR_NO})
+ list(APPEND RELOCATION_VARS _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX})
# point path relocated
- list(APPEND _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX} "${PAIR_NO}")
- list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_X_${POINT_INDEX}")
+ list(APPEND _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX} ${PAIR_NO})
+ list(APPEND RELOCATION_VARS _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX})
endforeach()
endforeach()
elseif(POINT_PATHS_COUNT)
@@ -476,22 +489,18 @@
list(FIND PACKAGE_PREFIXES "${POINT_RELOC_PATH}" POINT_INDEX)
# point path relocated
- list(APPEND _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX} "${PAIR_NO}")
- list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_X_${POINT_INDEX}")
+ list(APPEND _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX} ${PAIR_NO})
+ list(APPEND RELOCATION_VARS _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX})
endforeach()
endif()
# no path relocated
- list(APPEND _RPM_RELOCATION_SCRIPT_X_X "${PAIR_NO}")
- list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_X_X")
+ list(APPEND _RPM_RELOCATION_SCRIPT_X_X ${PAIR_NO})
+ list(APPEND RELOCATION_VARS _RPM_RELOCATION_SCRIPT_X_X)
- # place variables into parent scope
- foreach(VAR IN LISTS RELOCATION_VARS)
- set(${VAR} "${${VAR}}" PARENT_SCOPE)
- endforeach()
- set(_RPM_RELOCATION_SCRIPT_PAIRS "${_RPM_RELOCATION_SCRIPT_PAIRS}" PARENT_SCOPE)
- set(REQUIRES_SYMLINK_RELOCATION_SCRIPT "true" PARENT_SCOPE)
- set(DIRECTIVE "%ghost " PARENT_SCOPE)
+ set(REQUIRES_SYMLINK_RELOCATION_SCRIPT "true")
+ set(DIRECTIVE "%ghost ")
+ return(PROPAGATE _RPM_RELOCATION_SCRIPT_PAIRS REQUIRES_SYMLINK_RELOCATION_SCRIPT DIRECTIVE ${RELOCATION_VARS})
endfunction()
function(cpack_rpm_prepare_install_files INSTALL_FILES_LIST WDIR PACKAGE_PREFIXES IS_RELOCATABLE)
@@ -514,40 +523,26 @@
if(IS_SYMLINK "${WDIR}/${F}")
if(IS_RELOCATABLE)
# check that symlink has relocatable format
- get_filename_component(SYMLINK_LOCATION_ "${WDIR}/${F}" DIRECTORY)
- execute_process(COMMAND ls -la "${WDIR}/${F}"
- WORKING_DIRECTORY "${WDIR}"
- OUTPUT_VARIABLE SYMLINK_POINT_
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- string(FIND "${SYMLINK_POINT_}" "->" SYMLINK_POINT_INDEX_ REVERSE)
- math(EXPR SYMLINK_POINT_INDEX_ ${SYMLINK_POINT_INDEX_}+3)
- string(LENGTH "${SYMLINK_POINT_}" SYMLINK_POINT_LENGTH_)
-
- # get destination path
- string(SUBSTRING "${SYMLINK_POINT_}" ${SYMLINK_POINT_INDEX_} ${SYMLINK_POINT_LENGTH_} SYMLINK_POINT_)
+ cmake_path(APPEND_STRING WDIR "${F}" OUTPUT_VARIABLE SYMLINK_LOCATION_)
+ cmake_path(GET SYMLINK_LOCATION_ PARENT_PATH SYMLINK_LOCATION_)
+ file(READ_SYMLINK "${WDIR}/${F}" SYMLINK_POINT_)
# check if path is relative or absolute
- string(SUBSTRING "${SYMLINK_POINT_}" 0 1 SYMLINK_IS_ABSOLUTE_)
-
- if(${SYMLINK_IS_ABSOLUTE_} STREQUAL "/")
+ if(IS_ABSOLUTE "${SYMLINK_POINT_}")
# prevent absolute paths from having /../ or /./ section inside of them
- get_filename_component(SYMLINK_POINT_ "${SYMLINK_POINT_}" ABSOLUTE)
+ cmake_path(NORMAL_PATH SYMLINK_POINT_)
else()
# handle relative path
- get_filename_component(SYMLINK_POINT_ "${SYMLINK_LOCATION_}/${SYMLINK_POINT_}" ABSOLUTE)
+ cmake_path(ABSOLUTE_PATH SYMLINK_POINT_ BASE_DIRECTORY "${SYMLINK_LOCATION_}" NORMALIZE)
endif()
- # recalculate path length after conversion to canonical form
- string(LENGTH "${SYMLINK_POINT_}" SYMLINK_POINT_LENGTH_)
-
- cpack_rpm_exact_regex(IN_SYMLINK_POINT_REGEX "${WDIR}")
+ string(REGEX QUOTE IN_SYMLINK_POINT_REGEX "${WDIR}")
string(APPEND IN_SYMLINK_POINT_REGEX "/.*")
if(SYMLINK_POINT_ MATCHES "${IN_SYMLINK_POINT_REGEX}")
# only symlinks that are pointing inside the packaging structure should be checked for relocation
string(SUBSTRING "${SYMLINK_POINT_}" ${WDR_LEN_} -1 SYMLINK_POINT_WD_)
- cpack_rpm_symlink_get_relocation_prefixes("${F}" "${PACKAGE_PREFIXES}" "SYMLINK_RELOCATIONS")
- cpack_rpm_symlink_get_relocation_prefixes("${SYMLINK_POINT_WD_}" "${PACKAGE_PREFIXES}" "POINT_RELOCATIONS")
+ cpack_rpm_symlink_get_relocation_prefixes("${F}" "${PACKAGE_PREFIXES}" SYMLINK_RELOCATIONS)
+ cpack_rpm_symlink_get_relocation_prefixes("${SYMLINK_POINT_WD_}" "${PACKAGE_PREFIXES}" POINT_RELOCATIONS)
list(LENGTH SYMLINK_RELOCATIONS SYMLINK_RELOCATIONS_COUNT)
list(LENGTH POINT_RELOCATIONS POINT_RELOCATIONS_COUNT)
@@ -560,24 +555,32 @@
unset(SYMLINK_RELOCATIONS_COUNT)
unset(POINT_RELOCATIONS_COUNT)
- message(AUTHOR_WARNING "CPackRPM:Warning: Symbolic link '${F}' points to location that is outside packaging path! Link will possibly not be relocatable.")
+ message(
+ AUTHOR_WARNING
+ "CPackRPM:Warning: Symbolic link '${F}' points to location that is outside packaging path! "
+ "Link will possibly not be relocatable."
+ )
endif()
if(SYMLINK_RELOCATIONS_COUNT AND POINT_RELOCATIONS_COUNT)
# find matching
foreach(SYMLINK_RELOCATION_PREFIX IN LISTS SYMLINK_RELOCATIONS)
list(FIND POINT_RELOCATIONS "${SYMLINK_RELOCATION_PREFIX}" FOUND_INDEX)
- if(NOT ${FOUND_INDEX} EQUAL -1)
+ if(NOT FOUND_INDEX EQUAL -1)
break()
endif()
endforeach()
- if(NOT ${FOUND_INDEX} EQUAL -1)
+ if(NOT FOUND_INDEX EQUAL -1)
# symlinks have the same subpath
- if(${SYMLINK_RELOCATIONS_COUNT} EQUAL 1 AND ${POINT_RELOCATIONS_COUNT} EQUAL 1)
+ if(SYMLINK_RELOCATIONS_COUNT EQUAL 1 AND POINT_RELOCATIONS_COUNT EQUAL 1)
# permanent symlink
- get_filename_component(SYMLINK_LOCATION_ "${F}" DIRECTORY)
- file(RELATIVE_PATH FINAL_PATH_ ${SYMLINK_LOCATION_} ${SYMLINK_POINT_WD_})
+ cmake_path(GET F PARENT_PATH SYMLINK_LOCATION_)
+ cmake_path(
+ RELATIVE_PATH SYMLINK_POINT_WD_
+ BASE_DIRECTORY "${SYMLINK_LOCATION_}"
+ OUTPUT_VARIABLE FINAL_PATH_
+ )
execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${FINAL_PATH_}" "${WDIR}/${F}")
else()
# relocation subpaths
@@ -610,8 +613,8 @@
cpack_rpm_symlink_create_relocation_script("${PACKAGE_PREFIXES}")
endif()
- set(RPM_SYMLINK_POSTINSTALL "${RPM_SYMLINK_POSTINSTALL}" PARENT_SCOPE)
- set(CPACK_RPM_INSTALL_FILES "${INSTALL_FILES}" PARENT_SCOPE)
+ set(CPACK_RPM_INSTALL_FILES "${INSTALL_FILES}")
+ return(PROPAGATE RPM_SYMLINK_POSTINSTALL CPACK_RPM_INSTALL_FILES)
endfunction()
if(CMAKE_BINARY_DIR)
@@ -656,15 +659,14 @@
continue()
endif()
- execute_process(COMMAND "${CPACK_OBJDUMP_EXECUTABLE}" -h ${WORKING_DIR}/${F}
+ execute_process(COMMAND "${CPACK_OBJDUMP_EXECUTABLE}" -h "${WORKING_DIR}/${F}"
WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}"
RESULT_VARIABLE OBJDUMP_EXEC_RESULT
OUTPUT_VARIABLE OBJDUMP_OUT
ERROR_QUIET)
# Check if the given file is an executable or not
if(NOT OBJDUMP_EXEC_RESULT)
- string(FIND "${OBJDUMP_OUT}" "debug" FIND_RESULT)
- if(FIND_RESULT GREATER -1)
+ if(OBJDUMP_OUT MATCHES "debug")
set(index_ 0)
foreach(source_dir_ IN LISTS CPACK_BUILD_SOURCE_DIRS)
string(LENGTH "${source_dir_}" source_dir_len_)
@@ -679,23 +681,37 @@
" CPACK_RPM_DEBUGINFO_PACKAGE variable for details.")
endif()
- file(REMOVE "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}/debugsources_add.list")
- execute_process(COMMAND "${DEBUGEDIT_EXECUTABLE}" -b "${source_dir_}" -d "${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}" -i -l "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}/debugsources_add.list" "${WORKING_DIR}/${F}"
+ cmake_path(
+ APPEND CPACK_RPM_DIRECTORY "${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}/debugsources_add.list"
+ OUTPUT_VARIABLE debugsources_file_
+ )
+ file(REMOVE "${debugsources_file_}")
+ execute_process(
+ COMMAND "${DEBUGEDIT_EXECUTABLE}"
+ -b "${source_dir_}"
+ -d "${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}"
+ -i
+ -l "${debugsources_file_}"
+ "${WORKING_DIR}/${F}"
RESULT_VARIABLE res_
OUTPUT_VARIABLE opt_
ERROR_VARIABLE err_
)
- file(STRINGS
- "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}/debugsources_add.list"
- sources_)
+ file(STRINGS "${debugsources_file_}" sources_)
list(REMOVE_DUPLICATES sources_)
foreach(source_ IN LISTS sources_)
if(EXISTS "${source_dir_}/${source_}" AND NOT IS_DIRECTORY "${source_dir_}/${source_}")
- get_filename_component(path_part_ "${source_}" DIRECTORY)
- list(APPEND mkdir_list_ "%{buildroot}${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}/${path_part_}")
- list(APPEND cp_list_ "cp \"${source_dir_}/${source_}\" \"%{buildroot}${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}/${path_part_}\"")
+ cmake_path(GET source_ PARENT_PATH path_part_)
+ list(
+ APPEND mkdir_list_
+ "%{buildroot}${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}/${path_part_}"
+ )
+ list(
+ APPEND cp_list_
+ "cp \"${source_dir_}/${source_}\" \"%{buildroot}${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}/${path_part_}\""
+ )
list(APPEND additional_sources_ "${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}/src_${index_}/${source_}")
endif()
@@ -704,7 +720,11 @@
math(EXPR index_ "${index_} + 1")
endforeach()
else()
- message(WARNING "CPackRPM: File: ${F} does not contain debug symbols. They will possibly be missing from debuginfo package!")
+ message(
+ WARNING
+ "CPackRPM: File: ${F} does not contain debug symbols. "
+ "They will possibly be missing from debuginfo package!"
+ )
endif()
get_file_permissions("${WORKING_DIR}/${F}" permissions_)
@@ -712,7 +732,7 @@
NOT "GROUP_EXECUTE" IN_LIST permissions_ AND
NOT "WORLD_EXECUTE" IN_LIST permissions_)
if(CPACK_RPM_INSTALL_WITH_EXEC)
- execute_process(COMMAND chmod a+x ${WORKING_DIR}/${F}
+ execute_process(COMMAND chmod a+x "${WORKING_DIR}/${F}"
RESULT_VARIABLE res_
ERROR_VARIABLE err_
OUTPUT_QUIET)
@@ -788,9 +808,7 @@
endforeach()
endif()
- set(TMP_RPM_DEBUGINFO_INSTALL "${TMP_RPM_DEBUGINFO_INSTALL}" PARENT_SCOPE)
- set(TMP_DEBUGINFO_ADDITIONAL_SOURCES "${TMP_DEBUGINFO_ADDITIONAL_SOURCES}"
- PARENT_SCOPE)
+ return(PROPAGATE TMP_RPM_DEBUGINFO_INSTALL TMP_DEBUGINFO_ADDITIONAL_SOURCES)
endfunction()
function(cpack_rpm_variable_fallback OUTPUT_VAR_NAME)
@@ -798,8 +816,8 @@
foreach(variable_name IN LISTS FALLBACK_VAR_NAMES)
if(DEFINED ${variable_name})
- set(${OUTPUT_VAR_NAME} "${${variable_name}}" PARENT_SCOPE)
- break()
+ set(${OUTPUT_VAR_NAME} "${${variable_name}}")
+ return(PROPAGATE ${OUTPUT_VAR_NAME})
endif()
endforeach()
endfunction()
@@ -843,7 +861,7 @@
string(REGEX REPLACE "\n" ", "
LSB_RELEASE_OUTPUT
${_TMP_LSB_RELEASE_OUTPUT})
- else ()
+ else()
set(LSB_RELEASE_OUTPUT "lsb_release not installed/found!")
endif()
message("CPackRPM:Debug: LSB_RELEASE = ${LSB_RELEASE_OUTPUT}")
@@ -853,16 +871,23 @@
# to shut down warning about space in buildtree
# some recent RPM version should support space in different places.
# not checked [yet].
- if(CPACK_TOPLEVEL_DIRECTORY MATCHES ".* .*")
- message(FATAL_ERROR "${RPMBUILD_EXECUTABLE} can't handle paths with spaces, use a build directory without spaces for building RPMs.")
+ if(CPACK_TOPLEVEL_DIRECTORY MATCHES " ")
+ message(
+ FATAL_ERROR
+ "${RPMBUILD_EXECUTABLE} can't handle paths with spaces, use a build directory "
+ "without spaces for building RPMs."
+ )
endif()
# Are we packaging components ?
if(CPACK_RPM_PACKAGE_COMPONENT)
- string(TOUPPER ${CPACK_RPM_PACKAGE_COMPONENT} CPACK_RPM_PACKAGE_COMPONENT_UPPER)
+ string(TOUPPER "${CPACK_RPM_PACKAGE_COMPONENT}" CPACK_RPM_PACKAGE_COMPONENT_UPPER)
endif()
- set(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}")
+ cmake_path(
+ APPEND CPACK_TOPLEVEL_DIRECTORY "${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
+ OUTPUT_VARIABLE WDIR
+ )
#
# Use user-defined RPM specific variables value
@@ -876,9 +901,9 @@
# CPACK_RPM_PACKAGE_SUMMARY (mandatory)
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_SUMMARY"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_SUMMARY"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_SUMMARY")
+ cpack_rpm_variable_fallback(CPACK_RPM_PACKAGE_SUMMARY
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_SUMMARY
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_SUMMARY)
endif()
if(NOT CPACK_RPM_PACKAGE_SUMMARY)
@@ -900,15 +925,14 @@
endif()
if(CPACK_RPM_PACKAGE_COMPONENT)
- string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}"
- CPACK_RPM_MAIN_COMPONENT_UPPER)
+ string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}" CPACK_RPM_MAIN_COMPONENT_UPPER)
if(NOT CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER)
string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}")
- cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_NAME"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME")
+ cpack_rpm_variable_fallback(CPACK_RPM_PACKAGE_NAME
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME)
endif()
endif()
@@ -937,9 +961,9 @@
endif()
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_ARCHITECTURE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_ARCHITECTURE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_ARCHITECTURE")
+ cpack_rpm_variable_fallback(CPACK_RPM_PACKAGE_ARCHITECTURE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_ARCHITECTURE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_ARCHITECTURE)
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: using component build arch = ${CPACK_RPM_PACKAGE_ARCHITECTURE}")
@@ -961,7 +985,7 @@
# This is the case when the packaging is buggy (not) the software :=)
# If not set, 1 is a good candidate
if(NOT CPACK_RPM_PACKAGE_RELEASE)
- set(CPACK_RPM_PACKAGE_RELEASE "1")
+ set(CPACK_RPM_PACKAGE_RELEASE 1)
endif()
if(CPACK_RPM_PACKAGE_RELEASE_DIST)
@@ -970,18 +994,18 @@
# CPACK_RPM_PACKAGE_LICENSE
if(NOT CPACK_RPM_PACKAGE_LICENSE)
- set(CPACK_RPM_PACKAGE_LICENSE "unknown")
+ set(CPACK_RPM_PACKAGE_LICENSE unknown)
endif()
# CPACK_RPM_PACKAGE_GROUP
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_GROUP"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_GROUP"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_GROUP")
+ cpack_rpm_variable_fallback(CPACK_RPM_PACKAGE_GROUP
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_GROUP
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_GROUP)
endif()
if(NOT CPACK_RPM_PACKAGE_GROUP)
- set(CPACK_RPM_PACKAGE_GROUP "unknown")
+ set(CPACK_RPM_PACKAGE_GROUP unknown)
endif()
# CPACK_RPM_PACKAGE_VENDOR
@@ -989,7 +1013,7 @@
if(CPACK_PACKAGE_VENDOR)
set(CPACK_RPM_PACKAGE_VENDOR "${CPACK_PACKAGE_VENDOR}")
else()
- set(CPACK_RPM_PACKAGE_VENDOR "unknown")
+ set(CPACK_RPM_PACKAGE_VENDOR unknown)
endif()
endif()
@@ -1005,23 +1029,23 @@
#
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_DESCRIPTION"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_DESCRIPTION"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_DESCRIPTION"
- "CPACK_COMPONENT_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DESCRIPTION")
+ cpack_rpm_variable_fallback(CPACK_RPM_PACKAGE_DESCRIPTION
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_DESCRIPTION
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_DESCRIPTION
+ CPACK_COMPONENT_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DESCRIPTION)
endif()
if(NOT CPACK_RPM_PACKAGE_DESCRIPTION)
if(CPACK_PACKAGE_DESCRIPTION_FILE)
- file(READ ${CPACK_PACKAGE_DESCRIPTION_FILE} CPACK_RPM_PACKAGE_DESCRIPTION)
- else ()
+ file(READ "${CPACK_PACKAGE_DESCRIPTION_FILE}" CPACK_RPM_PACKAGE_DESCRIPTION)
+ else()
set(CPACK_RPM_PACKAGE_DESCRIPTION "no package description available")
- endif ()
- endif ()
+ endif()
+ endif()
# CPACK_RPM_COMPRESSION_TYPE
#
- if (CPACK_RPM_COMPRESSION_TYPE)
+ if(CPACK_RPM_COMPRESSION_TYPE)
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: User Specified RPM compression type: ${CPACK_RPM_COMPRESSION_TYPE}")
endif()
@@ -1056,7 +1080,11 @@
message("CPackRPM:Debug: Trying to build a relocatable package")
endif()
if(CPACK_SET_DESTDIR AND (NOT CPACK_SET_DESTDIR STREQUAL "I_ON"))
- message("CPackRPM:Warning: CPACK_SET_DESTDIR is set (=${CPACK_SET_DESTDIR}) while requesting a relocatable package (CPACK_RPM_PACKAGE_RELOCATABLE is set): this is not supported, the package won't be relocatable.")
+ message(
+ "CPackRPM:Warning: CPACK_SET_DESTDIR is set (=${CPACK_SET_DESTDIR}) while requesting a "
+ "relocatable package (CPACK_RPM_PACKAGE_RELOCATABLE is set): this is not supported, "
+ "the package won't be relocatable."
+ )
set(CPACK_RPM_PACKAGE_RELOCATABLE FALSE)
else()
set(CPACK_RPM_PACKAGE_PREFIX ${CPACK_PACKAGING_INSTALL_PREFIX}) # kept for back compatibility (provided external RPM spec files)
@@ -1098,7 +1126,7 @@
ERROR_QUIET
RESULT_VARIABLE RPM_SUGGESTS_RESULT)
if(NOT RPM_SUGGESTS_RESULT EQUAL 0)
- foreach(_WEAK_DEP SUGGESTS RECOMMENDS SUPPLEMENTS ENHANCES)
+ foreach(_WEAK_DEP IN ITEMS SUGGESTS RECOMMENDS SUPPLEMENTS ENHANCES)
list(REMOVE_ITEM RPMBUILD_TAG_LIST ${_WEAK_DEP})
endforeach()
endif()
@@ -1112,16 +1140,22 @@
# There may be some COMPONENT specific variables as well
# If component specific var is not provided we use the global one
# for each component
- foreach(_RPM_SPEC_HEADER URL REQUIRES SUGGESTS RECOMMENDS SUPPLEMENTS ENHANCES PROVIDES OBSOLETES PREFIX CONFLICTS AUTOPROV AUTOREQ AUTOREQPROV REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN)
+ set(
+ tags_
+ URL REQUIRES SUGGESTS RECOMMENDS SUPPLEMENTS ENHANCES PROVIDES
+ OBSOLETES PREFIX CONFLICTS AUTOPROV AUTOREQ AUTOREQPROV
+ REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN
+ )
+ foreach(_RPM_SPEC_HEADER IN LISTS tags_)
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: processing ${_RPM_SPEC_HEADER}")
endif()
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_${_RPM_SPEC_HEADER}")
+ cpack_rpm_variable_fallback(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_${_RPM_SPEC_HEADER})
endif()
if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER})
@@ -1153,8 +1187,7 @@
string(APPEND _PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_TAIL}")
# The following keywords require parentheses around the "pre" or "post" suffix in the final RPM spec file.
set(SCRIPTS_REQUIREMENTS_LIST REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN)
- list(FIND SCRIPTS_REQUIREMENTS_LIST ${_RPM_SPEC_HEADER} IS_SCRIPTS_REQUIREMENT_FOUND)
- if(NOT ${IS_SCRIPTS_REQUIREMENT_FOUND} EQUAL -1)
+ if(_RPM_SPEC_HEADER IN_LIST SCRIPTS_REQUIREMENTS_LIST)
string(REPLACE "_" "(" _PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME}")
string(APPEND _PACKAGE_HEADER_NAME ")")
endif()
@@ -1200,29 +1233,32 @@
# May be used to embed a pre installation/uninstallation/transaction script in the spec file.
# The referred script file(s) will be read and directly
# put after the %pre or %preun or %pretrans section
- foreach(RPM_SCRIPT_FILE_TYPE_ "INSTALL" "UNINSTALL" "TRANS")
- foreach(RPM_SCRIPT_FILE_TIME_ "PRE" "POST")
- set("CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE"
+ foreach(RPM_SCRIPT_FILE_TYPE_ IN ITEMS INSTALL UNINSTALL TRANS)
+ foreach(RPM_SCRIPT_FILE_TIME_ IN ITEMS PRE POST)
+ set(CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE
"${CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE}")
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE")
+ cpack_rpm_variable_fallback(CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE)
endif()
# Handle file if it has been specified
if(CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE)
if(EXISTS ${CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE})
- file(READ ${CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE}
- "CPACK_RPM_SPEC_${RPM_SCRIPT_FILE_TIME_}${RPM_SCRIPT_FILE_TYPE_}")
+ file(READ "${CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE}"
+ CPACK_RPM_SPEC_${RPM_SCRIPT_FILE_TIME_}${RPM_SCRIPT_FILE_TYPE_})
else()
- message("CPackRPM:Warning: CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE <${CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE}> does not exist - ignoring")
+ message(
+ "CPackRPM:Warning: CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_SCRIPT_FILE "
+ "<${CPACK_RPM_${RPM_SCRIPT_FILE_TIME_}_${RPM_SCRIPT_FILE_TYPE_}_READ_FILE}> does not exist - ignoring"
+ )
endif()
else()
# reset SPEC var value if no file has been specified
# (either globally or component-wise)
- set("CPACK_RPM_SPEC_${RPM_SCRIPT_FILE_TIME_}${RPM_SCRIPT_FILE_TYPE_}" "")
+ set(CPACK_RPM_SPEC_${RPM_SCRIPT_FILE_TIME_}${RPM_SCRIPT_FILE_TYPE_} "")
endif()
endforeach()
endforeach()
@@ -1232,17 +1268,26 @@
# The referred file will be read and directly put after the %changelog section
if(CPACK_RPM_CHANGELOG_FILE)
if(EXISTS ${CPACK_RPM_CHANGELOG_FILE})
- file(READ ${CPACK_RPM_CHANGELOG_FILE} CPACK_RPM_SPEC_CHANGELOG)
+ file(READ "${CPACK_RPM_CHANGELOG_FILE}" CPACK_RPM_SPEC_CHANGELOG)
else()
message(SEND_ERROR "CPackRPM:Warning: CPACK_RPM_CHANGELOG_FILE <${CPACK_RPM_CHANGELOG_FILE}> does not exist - ignoring")
endif()
else()
- set(CPACK_RPM_SPEC_CHANGELOG "* Sun Jul 4 2010 Eric Noulard <eric.noulard@gmail.com> - ${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n Generated by CPack RPM (no Changelog file were provided)")
+ set(
+ CPACK_RPM_SPEC_CHANGELOG
+ "* Sun Jul 4 2010 Eric Noulard <eric.noulard@gmail.com> - ${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}"
+ " Generated by CPack RPM (no Changelog file were provided)"
+ )
+ list(JOIN CPACK_RPM_SPEC_CHANGELOG "\n" CPACK_RPM_SPEC_CHANGELOG)
endif()
# CPACK_RPM_SPEC_MORE_DEFINE
# This is a generated spec rpm file spaceholder
if(CPACK_RPM_SPEC_MORE_DEFINE)
+ list(LENGTH CPACK_RPM_SPEC_MORE_DEFINE _defines_size)
+ if(_defines_size GREATER 1)
+ list(JOIN CPACK_RPM_SPEC_MORE_DEFINE "\n" CPACK_RPM_SPEC_MORE_DEFINE)
+ endif()
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: User defined more define spec line specified:\n ${CPACK_RPM_SPEC_MORE_DEFINE}")
endif()
@@ -1254,13 +1299,15 @@
message("CPackRPM:Debug: Using CPACK_RPM_ROOTDIR=${CPACK_RPM_ROOTDIR}")
endif()
# Prepare RPM build tree
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR})
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/tmp)
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/BUILD)
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/RPMS)
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SOURCES)
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SPECS)
- file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SRPMS)
+ file(
+ MAKE_DIRECTORY
+ ${CPACK_RPM_ROOTDIR}/tmp
+ ${CPACK_RPM_ROOTDIR}/BUILD
+ ${CPACK_RPM_ROOTDIR}/RPMS
+ ${CPACK_RPM_ROOTDIR}/SOURCES
+ ${CPACK_RPM_ROOTDIR}/SPECS
+ ${CPACK_RPM_ROOTDIR}/SRPMS
+ )
# it seems rpmbuild can't handle spaces in the path
# neither escaping (as below) nor putting quotes around the path seem to help
@@ -1275,9 +1322,9 @@
# This must be done BEFORE the CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL handling
if(CPACK_RPM_PACKAGE_COMPONENT)
if(CPACK_ABSOLUTE_DESTINATION_FILES)
- cpack_rpm_variable_fallback("COMPONENT_FILES_TAG"
- "CPACK_ABSOLUTE_DESTINATION_FILES_${CPACK_RPM_PACKAGE_COMPONENT}"
- "CPACK_ABSOLUTE_DESTINATION_FILES_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}")
+ cpack_rpm_variable_fallback(COMPONENT_FILES_TAG
+ CPACK_ABSOLUTE_DESTINATION_FILES_${CPACK_RPM_PACKAGE_COMPONENT}
+ CPACK_ABSOLUTE_DESTINATION_FILES_${CPACK_RPM_PACKAGE_COMPONENT_UPPER})
set(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL "${${COMPONENT_FILES_TAG}}")
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: Handling Absolute Destination Files: <${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}>")
@@ -1293,9 +1340,9 @@
# In component case, set CPACK_RPM_USER_FILELIST_INTERNAL with CPACK_RPM_<COMPONENT>_USER_FILELIST.
set(CPACK_RPM_USER_FILELIST_INTERNAL "")
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_USER_FILELIST_INTERNAL"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_FILELIST"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_USER_FILELIST")
+ cpack_rpm_variable_fallback(CPACK_RPM_USER_FILELIST_INTERNAL
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_FILELIST
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_USER_FILELIST)
if(CPACK_RPM_PACKAGE_DEBUG AND CPACK_RPM_USER_FILELIST_INTERNAL)
message("CPackRPM:Debug: Handling User Filelist: <${CPACK_RPM_USER_FILELIST_INTERNAL}>")
@@ -1340,7 +1387,7 @@
# Remove from CPACK_RPM_INSTALL_FILES and CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL
list(REMOVE_ITEM CPACK_RPM_INSTALL_FILES_LIST ${F_PATH})
# ABSOLUTE destination files list may not exists at all
- if (CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL)
+ if(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL)
list(REMOVE_ITEM CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL ${F_PATH})
endif()
endforeach()
@@ -1355,7 +1402,7 @@
set(CPACK_RPM_USER_INSTALL_FILES "")
endif()
- if (CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL)
+ if(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL)
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: Handling Absolute Destination Files: ${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}")
endif()
@@ -1388,24 +1435,22 @@
set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "")
endif()
- cpack_rpm_variable_fallback("CPACK_RPM_DEBUGINFO_PACKAGE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_PACKAGE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_PACKAGE"
- "CPACK_RPM_DEBUGINFO_PACKAGE")
+ cpack_rpm_variable_fallback(CPACK_RPM_DEBUGINFO_PACKAGE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_PACKAGE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_PACKAGE
+ CPACK_RPM_DEBUGINFO_PACKAGE)
if(CPACK_RPM_DEBUGINFO_PACKAGE OR (CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND NOT GENERATE_SPEC_PARTS))
- cpack_rpm_variable_fallback("CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_BUILD_SOURCE_DIRS_PREFIX"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_BUILD_SOURCE_DIRS_PREFIX"
- "CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX")
+ cpack_rpm_variable_fallback(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_BUILD_SOURCE_DIRS_PREFIX
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_BUILD_SOURCE_DIRS_PREFIX
+ CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX)
if(NOT CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX)
set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/src/debug/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}")
endif()
# handle cases where path contains extra slashes (e.g. /a//b/ instead of
# /a/b)
- get_filename_component(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX
- "${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}" ABSOLUTE)
-
+ cmake_path(ABSOLUTE_PATH CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX NORMALIZE)
if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS)
file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.files"
"${CPACK_RPM_INSTALL_FILES}")
@@ -1456,7 +1501,7 @@
continue()
endif()
- get_filename_component(dir_path_ "${f_}" DIRECTORY)
+ cmake_path(GET f_ PARENT_PATH dir_path_)
# check that we are not overriding an existing file that doesn't
# match the file that we want to copy
@@ -1473,8 +1518,7 @@
endif()
file(MAKE_DIRECTORY "${WDIR}/${dir_path_}")
- file(RENAME "${src_file_}"
- "${WDIR}/${f_}")
+ file(RENAME "${src_file_}" "${WDIR}/${f_}")
endforeach()
endforeach()
@@ -1527,31 +1571,40 @@
)
# set default user and group
- foreach(_PERM_TYPE "USER" "GROUP")
+ foreach(_PERM_TYPE IN ITEMS USER GROUP)
if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE})
set(TMP_DEFAULT_${_PERM_TYPE} "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}}")
elseif(CPACK_RPM_DEFAULT_${_PERM_TYPE})
set(TMP_DEFAULT_${_PERM_TYPE} "${CPACK_RPM_DEFAULT_${_PERM_TYPE}}")
else()
- set(TMP_DEFAULT_${_PERM_TYPE} "root")
+ set(TMP_DEFAULT_${_PERM_TYPE} root)
endif()
endforeach()
# set default file and dir permissions
- foreach(_PERM_TYPE "FILE" "DIR")
+ foreach(_PERM_TYPE IN ITEMS FILE DIR)
if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS)
- get_unix_permissions_octal_notation("CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS" "TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS")
- set(_PERMISSIONS_VAR "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS")
+ get_unix_permissions_octal_notation(
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS
+ TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS
+ )
+ set(_PERMISSIONS_VAR CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEFAULT_${_PERM_TYPE}_PERMISSIONS)
elseif(CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS)
- get_unix_permissions_octal_notation("CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS" "TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS")
- set(_PERMISSIONS_VAR "CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS")
+ get_unix_permissions_octal_notation(
+ CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS
+ TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS
+ )
+ set(_PERMISSIONS_VAR CPACK_RPM_DEFAULT_${_PERM_TYPE}_PERMISSIONS)
else()
- set(TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS "-")
+ set(TMP_DEFAULT_${_PERM_TYPE}_PERMISSIONS -)
endif()
endforeach()
# The name of the final spec file to be used by rpmbuild
- set(CPACK_RPM_BINARY_SPECFILE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_NAME}.spec")
+ cmake_path(
+ APPEND CPACK_RPM_ROOTDIR "SPECS/${CPACK_RPM_PACKAGE_NAME}.spec"
+ OUTPUT_VARIABLE CPACK_RPM_BINARY_SPECFILE
+ )
# Print out some debug information if we were asked for that
if(CPACK_RPM_PACKAGE_DEBUG)
@@ -1572,15 +1625,15 @@
# We can have a component specific spec file.
if(CPACK_RPM_PACKAGE_COMPONENT)
- cpack_rpm_variable_fallback("CPACK_RPM_USER_BINARY_SPECFILE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_USER_BINARY_SPECFILE")
+ cpack_rpm_variable_fallback(CPACK_RPM_USER_BINARY_SPECFILE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_USER_BINARY_SPECFILE)
endif()
- cpack_rpm_variable_fallback("CPACK_RPM_FILE_NAME"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_FILE_NAME"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_FILE_NAME"
- "CPACK_RPM_FILE_NAME")
+ cpack_rpm_variable_fallback(CPACK_RPM_FILE_NAME
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_FILE_NAME
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_FILE_NAME
+ CPACK_RPM_FILE_NAME)
if(NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT")
if(CPACK_RPM_FILE_NAME)
if(NOT CPACK_RPM_FILE_NAME MATCHES ".*\\.rpm")
@@ -1588,9 +1641,7 @@
endif()
else()
# old file name format for back compatibility
- string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}"
- CPACK_RPM_MAIN_COMPONENT_UPPER)
-
+ string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}" CPACK_RPM_MAIN_COMPONENT_UPPER)
if(CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER)
# this is the main component so ignore the component filename part
set(CPACK_RPM_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.rpm")
@@ -1650,7 +1701,7 @@
)
set(TMP_RPM_PREP "%setup -c")
- set(RPMBUILD_FLAGS "-bs")
+ set(RPMBUILD_FLAGS -bs)
file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in
"# Restore old style debuginfo creation for rpm >= 4.14.
@@ -1700,8 +1751,6 @@
%install
\@TMP_RPM_INSTALL\@
-%clean
-
%changelog
\@CPACK_RPM_SPEC_CHANGELOG\@
"
@@ -1773,7 +1822,7 @@
# We should generate a USER spec file template:
# - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE
# - or the user did not provide one : NOT CPACK_RPM_USER_BINARY_SPECFILE
- set(RPMBUILD_FLAGS "-bb")
+ set(RPMBUILD_FLAGS -bb)
if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE)
set_spec_scripts("")
@@ -1843,8 +1892,6 @@
\@TMP_RPM_DEBUGINFO_INSTALL\@
-%clean
-
\@post_\@
\@posttrans_\@
\@postun_\@
@@ -1911,10 +1958,10 @@
endif()
# find generated rpm files and take their names
- file(GLOB_RECURSE GENERATED_FILES "${CPACK_RPM_DIRECTORY}/RPMS/*.rpm"
+ file(GLOB_RECURSE GEN_CPACK_OUTPUT_FILES "${CPACK_RPM_DIRECTORY}/RPMS/*.rpm"
"${CPACK_RPM_DIRECTORY}/SRPMS/*.rpm")
- if(NOT GENERATED_FILES)
+ if(NOT GEN_CPACK_OUTPUT_FILES)
message(FATAL_ERROR "RPM package was not generated! ${CPACK_RPM_DIRECTORY}")
endif()
@@ -1927,10 +1974,10 @@
endif()
if(CPACK_RPM_DEBUGINFO_PACKAGE)
- cpack_rpm_variable_fallback("CPACK_RPM_DEBUGINFO_FILE_NAME"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_FILE_NAME"
- "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_FILE_NAME"
- "CPACK_RPM_DEBUGINFO_FILE_NAME")
+ cpack_rpm_variable_fallback(CPACK_RPM_DEBUGINFO_FILE_NAME
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_FILE_NAME
+ CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_FILE_NAME
+ CPACK_RPM_DEBUGINFO_FILE_NAME)
if(CPACK_RPM_DEBUGINFO_FILE_NAME AND
NOT CPACK_RPM_DEBUGINFO_FILE_NAME STREQUAL "RPM-DEFAULT")
@@ -1955,16 +2002,16 @@
endif()
if(expected_filenames_)
- foreach(F IN LISTS GENERATED_FILES)
- unset(matched_)
+ foreach(F IN LISTS GEN_CPACK_OUTPUT_FILES)
+ set(matched_ FALSE)
foreach(expected_ IN LISTS expected_filenames_)
if(F MATCHES ".*/${expected_}")
list(FIND expected_filenames_ "${expected_}" idx_)
list(GET filenames_ ${idx_} filename_)
- get_filename_component(FILE_PATH "${F}" DIRECTORY)
+ cmake_path(GET F PARENT_PATH FILE_PATH)
file(RENAME "${F}" "${FILE_PATH}/${filename_}")
list(APPEND new_files_list_ "${FILE_PATH}/${filename_}")
- set(matched_ "YES")
+ set(matched_ TRUE)
break()
endif()
@@ -1975,15 +2022,15 @@
endif()
endforeach()
- set(GENERATED_FILES "${new_files_list_}")
+ set(GEN_CPACK_OUTPUT_FILES "${new_files_list_}")
endif()
endif()
- set(GEN_CPACK_OUTPUT_FILES "${GENERATED_FILES}" PARENT_SCOPE)
-
if(CPACK_RPM_PACKAGE_DEBUG)
- message("CPackRPM:Debug: GEN_CPACK_OUTPUT_FILES = ${GENERATED_FILES}")
+ message("CPackRPM:Debug: GEN_CPACK_OUTPUT_FILES = ${GEN_CPACK_OUTPUT_FILES}")
endif()
+
+ return(PROPAGATE GEN_CPACK_OUTPUT_FILES)
endfunction()
cpack_rpm_generate_package()
diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake
index 64d477b..85f7217 100644
--- a/Modules/Internal/FeatureTesting.cmake
+++ b/Modules/Internal/FeatureTesting.cmake
@@ -37,6 +37,7 @@
LINK_LIBRARIES "${compile_flags_for_link}"
COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
COPY_FILE_ERROR _copy_error
+ NO_CACHE
__CMAKE_INTERNAL FEATURE_TESTING
)
if(NOT CMAKE_${lang}_FEATURE_TEST)
@@ -47,7 +48,7 @@
else()
set(_result 0)
endif()
- unset(CMAKE_${lang}_FEATURE_TEST CACHE)
+ unset(CMAKE_${lang}_FEATURE_TEST)
unset(compile_flags_for_link)
if (_result EQUAL 0)
diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList
index 064024b..ef6eada 100755
--- a/Modules/Platform/AIX/ExportImportList
+++ b/Modules/Platform/AIX/ExportImportList
@@ -43,7 +43,13 @@
# need to be handled differently.
#
# [0]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto
-NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm"
+if "$compiler" --version 2>/dev/null | grep -qi "IBM Open XL"; then
+ NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm"
+elif "$compiler" --version 2>/dev/null | grep -qi "[cf]lang version"; then
+ NM="$(dirname "$compiler")/../bin/llvm-nm"
+else
+ NM="nm"
+fi
function IsBitcode {
# N4 = first 4 bytes, -tx = output in hexadecimal, -An = don't display offset
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index bd0b301..bc73ecb 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -285,6 +285,8 @@
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86_64")
+ elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
+ set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-arm64")
else()
set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86")
endif()
diff --git a/Modules/Platform/Haiku.cmake b/Modules/Platform/Haiku.cmake
index 3610389..bf0e0fc 100644
--- a/Modules/Platform/Haiku.cmake
+++ b/Modules/Platform/Haiku.cmake
@@ -8,6 +8,12 @@
set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,")
set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic")
+# Features for LINK_GROUP generator expression
+## RESCAN: request the linker to rescan static libraries until there is
+## no pending undefined symbols
+set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group")
+set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE)
+
# Determine, if the C or C++ compiler is configured for a secondary
# architecture. If so, that will change the search paths we set below. We check
# whether the compiler's library search paths contain a
diff --git a/Modules/Platform/Linux-NAG-Fortran.cmake b/Modules/Platform/Linux-NAG-Fortran.cmake
index 353bae6..3bcd9b7 100644
--- a/Modules/Platform/Linux-NAG-Fortran.cmake
+++ b/Modules/Platform/Linux-NAG-Fortran.cmake
@@ -8,3 +8,16 @@
set(CMAKE_SHARED_LIBRARY_RPATH_LINK_Fortran_FLAG "-Wl,-Xlinker,-rpath-link,-Xlinker,")
set(CMAKE_SHARED_LIBRARY_SONAME_Fortran_FLAG "-Wl,-Xlinker,-soname,-Xlinker,")
set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-Wl,-rdynamic")
+
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,-Xlinker,")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+
+set(CMAKE_Fortran_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_Fortran_LINK_LIBRARY_USING_WHOLE_ARCHIVE
+ "LINKER:--whole-archive"
+ "<LINK_ITEM>"
+ "LINKER:--no-whole-archive")
+set(CMAKE_Fortran_LINK_LIBRARY_WHOLE_ARCHIVE_ATTRIBUTES
+ LIBRARY_TYPE=STATIC
+ OVERRIDE=DEFAULT
+ DEDUPLICATION=YES)
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index 0c002dd..0c3f6ab 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -207,19 +207,19 @@
if(NOT CMAKE_RC_COMPILER_INIT)
# Check if rc is already in the path
# This may happen in cases where the user is already in a visual studio environment when CMake is invoked
- find_program(__RC_COMPILER_PATH NAMES rc)
+ find_program(__RC_COMPILER_PATH NO_CACHE NAMES rc)
# Default to rc if it's available, otherwise fall back to llvm-rc
if(__RC_COMPILER_PATH)
set(CMAKE_RC_COMPILER_INIT rc)
else()
- find_program(__RC_COMPILER_PATH NAMES llvm-rc)
+ find_program(__RC_COMPILER_PATH NO_CACHE NAMES llvm-rc)
if(__RC_COMPILER_PATH)
set(CMAKE_RC_COMPILER_INIT llvm-rc)
endif()
endif()
- unset(__RC_COMPILER_PATH CACHE)
+ unset(__RC_COMPILER_PATH)
endif()
if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC"
diff --git a/Modules/Platform/Windows-OrangeC.cmake b/Modules/Platform/Windows-OrangeC.cmake
index 4f66e0e..a8f23e3 100644
--- a/Modules/Platform/Windows-OrangeC.cmake
+++ b/Modules/Platform/Windows-OrangeC.cmake
@@ -7,4 +7,11 @@
macro(__windows_compiler_orangec lang)
set(CMAKE_${lang}_CREATE_WIN32_EXE "-Wg")
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Wc")
+
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
+ if(NOT CMAKE_RC_COMPILER_INIT)
+ set(CMAKE_RC_COMPILER_INIT orc)
+ endif()
+ enable_language(RC)
+ endif()
endmacro()
diff --git a/Modules/Platform/Windows-PellesC-C.cmake b/Modules/Platform/Windows-PellesC-C.cmake
new file mode 100644
index 0000000..d933dcf
--- /dev/null
+++ b/Modules/Platform/Windows-PellesC-C.cmake
@@ -0,0 +1,5 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file LICENSE.rst or https://cmake.org/licensing for details.
+
+include (Platform/Windows-PellesC)
+__windows_compiler_pellesc(C)
diff --git a/Modules/Platform/Windows-PellesC.cmake b/Modules/Platform/Windows-PellesC.cmake
new file mode 100644
index 0000000..b30c7e2
--- /dev/null
+++ b/Modules/Platform/Windows-PellesC.cmake
@@ -0,0 +1,24 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file LICENSE.rst or https://cmake.org/licensing for details.
+include_guard()
+
+set(CMAKE_LIBRARY_PATH_FLAG "-libpath:")
+set(CMAKE_LINK_LIBRARY_FLAG "")
+
+macro(__windows_compiler_pellesc lang)
+ set(CMAKE_${lang}_COMPILE_OBJECT
+ "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -Fo<OBJECT> -c <SOURCE>")
+
+ set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <LINK_FLAGS> -out:<TARGET> <OBJECTS>")
+
+ set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
+ "<CMAKE_LINKER> <OBJECTS> -out:<TARGET> -implib:<TARGET_IMPLIB> -dll -version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_FLAGS> <LINK_LIBRARIES>")
+ set(CMAKE_${lang}_CREATE_SHARED_MODULE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}")
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "")
+
+ set(CMAKE_${lang}_LINK_EXECUTABLE
+ "<CMAKE_LINKER> <OBJECTS> -out:<TARGET> -implib:<TARGET_IMPLIB> -version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_FLAGS> <LINK_LIBRARIES>")
+
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "-subsystem:windows")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-subsystem:console")
+endmacro()
diff --git a/Modules/Platform/Windows-orc.cmake b/Modules/Platform/Windows-orc.cmake
new file mode 100644
index 0000000..1f8b08e
--- /dev/null
+++ b/Modules/Platform/Windows-orc.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -! <DEFINES> <INCLUDES> <FLAGS> -o<OBJECT> <SOURCE>")
+set(CMAKE_INCLUDE_FLAG_RC "-i ")
diff --git a/Modules/UseJava/javaTargets.cmake.in b/Modules/UseJava/javaTargets.cmake.in
index 7a88344..157a60e 100644
--- a/Modules/UseJava/javaTargets.cmake.in
+++ b/Modules/UseJava/javaTargets.cmake.in
@@ -1,5 +1,5 @@
cmake_policy(PUSH)
-cmake_policy(VERSION 2.8.12...4.1)
+cmake_policy(VERSION 2.8.12...4.2)
#----------------------------------------------------------------
# Generated CMake Java target import file.
diff --git a/README.rst b/README.rst
index 3eefaf9..a10da9c 100644
--- a/README.rst
+++ b/README.rst
@@ -89,6 +89,12 @@
$ mkdir build && cd build
$ ../bootstrap && make
+By default the ``bootstrap`` script configures CMake to build with vendored
+dependencies. However, CMake does not vendor OpenSSL. To bootstrap in a
+minimal environment, disable use of OpenSSL::
+
+ $ ./bootstrap -- -DCMAKE_USE_OPENSSL=OFF
+
Windows
^^^^^^^
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 0be5788..76449a8 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -187,12 +187,16 @@
cmDependsJavaParserHelper.h
cmDependsCompiler.cxx
cmDependsCompiler.h
+ cmDiagnostics.h
+ cmDiagnostics.cxx
cmDocumentation.cxx
cmDocumentationFormatter.cxx
cmDyndepCollation.cxx
cmDyndepCollation.h
cmELF.h
cmELF.cxx
+ cmEnvironment.cxx
+ cmEnvironment.h
cmEvaluatedTargetProperty.cxx
cmEvaluatedTargetProperty.h
cmExprParserHelper.cxx
@@ -270,6 +274,8 @@
cmFilePathChecksum.h
cmFileSet.cxx
cmFileSet.h
+ cmFileSetMetadata.cxx
+ cmFileSetMetadata.h
cmFileTime.cxx
cmFileTime.h
cmFileTimeCache.cxx
@@ -302,15 +308,19 @@
cmGeneratorExpressionParser.h
cmGeneratorExpression.cxx
cmGeneratorExpression.h
+ cmGeneratorFileSet.cxx
+ cmGeneratorFileSet.h
+ cmGeneratorFileSets.cxx
+ cmGeneratorFileSets.h
cmGeneratorTarget.cxx
cmGeneratorTarget.h
cmGeneratorTarget_CompatibleInterface.cxx
+ cmGeneratorTarget_HeaderSetVerification.cxx
cmGeneratorTarget_IncludeDirectories.cxx
cmGeneratorTarget_Link.cxx
cmGeneratorTarget_LinkDirectories.cxx
cmGeneratorTarget_Options.cxx
cmGeneratorTarget_Sources.cxx
- cmGeneratorTarget_TargetPropertyEntry.cxx
cmGeneratorTarget_TransitiveProperty.cxx
cmLinkItemGraphVisitor.cxx
cmLinkItemGraphVisitor.h
@@ -334,6 +344,8 @@
cmInstallAndroidMKExportGenerator.h
cmInstallCMakeConfigExportGenerator.cxx
cmInstallCMakeConfigExportGenerator.h
+ cmInstallDirs.cxx
+ cmInstallDirs.h
cmInstallGenerator.h
cmInstallGenerator.cxx
cmInstallGetRuntimeDependenciesGenerator.h
@@ -503,6 +515,8 @@
cmTarget.h
cmTargetPropertyComputer.cxx
cmTargetPropertyComputer.h
+ cmTargetPropertyEntry.cxx
+ cmTargetPropertyEntry.h
cmTargetExport.h
cmTargetTraceDependencies.cxx
cmTargetTraceDependencies.h
@@ -571,6 +585,8 @@
cmBreakCommand.h
cmBuildCommand.cxx
cmBuildCommand.h
+ cmCMakeDiagnosticCommand.cxx
+ cmCMakeDiagnosticCommand.h
cmCMakeHostSystemInformationCommand.cxx
cmCMakeHostSystemInformationCommand.h
cmCMakeLanguageCommand.cxx
@@ -595,6 +611,8 @@
cmCreateTestSourceList.h
cmDefinePropertyCommand.cxx
cmDefinePropertyCommand.h
+ cmDiscoverTestsCommand.cxx
+ cmDiscoverTestsCommand.h
cmEnableLanguageCommand.cxx
cmEnableLanguageCommand.h
cmEnableTestingCommand.cxx
@@ -1127,6 +1145,7 @@
CTest/cmCTestCoverageCommand.cxx
CTest/cmCTestCoverageHandler.cxx
CTest/cmCTestCurl.cxx
+ CTest/cmCTestDiscoverTests.cxx
CTest/cmParseMumpsCoverage.cxx
CTest/cmParseCacheCoverage.cxx
CTest/cmParseGTMCoverage.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 8b5ad85..b00209a 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 4)
set(CMake_VERSION_MINOR 3)
-set(CMake_VERSION_PATCH 1)
+set(CMake_VERSION_PATCH 20260415)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index e440b84..8b1e9b2 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -22,7 +22,6 @@
#include "cmList.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmUuid.h"
#include "cmValue.h"
#include "cmWIXDirectoriesSourceWriter.h"
#include "cmWIXFeaturesSourceWriter.h"
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index 9581d9f..821b00d 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -12,7 +12,6 @@
#include "cmCMakeToWixPath.h"
#include "cmInstalledFile.h"
#include "cmSystemTools.h"
-#include "cmUuid.h"
#include "cmWIXAccessControlList.h"
#ifdef _WIN32
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 8ee5637..e937fe0 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -361,7 +361,8 @@
} else if (status == DeduplicateStatus::Error) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"ERROR The data in files with the "
- "same filename is different.");
+ "same filename is different: "
+ << rp << std::endl);
return 0;
} else {
cmCPackLogger(cmCPackLog::LOG_DEBUG,
@@ -393,7 +394,7 @@
return 0; \
} \
cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat, \
- this->GetCompressionLevel(), \
+ this->GetEncoding(), this->GetCompressionLevel(), \
this->GetThreadCount()); \
if (this->UID >= 0 && this->GID >= 0) { \
archive.SetUIDAndGID(this->UID, this->GID); \
@@ -610,3 +611,14 @@
return level;
}
+
+std::string cmCPackArchiveGenerator::GetEncoding() const
+{
+ std::string encoding = "UTF-8";
+
+ if (cmValue v = this->GetOptionIfSet("CPACK_ARCHIVE_ENCODING")) {
+ encoding = *v;
+ }
+
+ return encoding;
+}
diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h
index 22c8bba..e295561 100644
--- a/Source/CPack/cmCPackArchiveGenerator.h
+++ b/Source/CPack/cmCPackArchiveGenerator.h
@@ -106,6 +106,7 @@
int GetThreadCount() const;
int GetCompressionLevel() const;
+ std::string GetEncoding() const;
private:
cmArchiveWrite::Compress Compress;
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 523a293..63e58a4 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -37,7 +37,8 @@
std::map<std::string, std::string> controlValues,
bool genShLibs, std::string shLibsFilename, bool genPostInst,
std::string postInst, bool genPostRm, std::string postRm,
- cmValue controlExtra, bool permissionStrctPolicy,
+ bool genTriggers, std::string triggers, cmValue controlExtra,
+ bool permissionStrctPolicy,
std::vector<std::string> packageFiles);
bool generate() const;
@@ -65,6 +66,8 @@
std::string const PostInst;
bool const GenPostRm;
std::string const PostRm;
+ bool const GenTriggers;
+ std::string const Triggers;
cmValue ControlExtra;
bool const PermissionStrictPolicy;
std::vector<std::string> const PackageFiles;
@@ -78,8 +81,8 @@
cmValue debCompressionType, cmValue debCompressionLevel, cmValue numThreads,
cmValue debianArchiveType, std::map<std::string, std::string> controlValues,
bool genShLibs, std::string shLibsFilename, bool genPostInst,
- std::string postInst, bool genPostRm, std::string postRm,
- cmValue controlExtra, bool permissionStrictPolicy,
+ std::string postInst, bool genPostRm, std::string postRm, bool genTriggers,
+ std::string triggers, cmValue controlExtra, bool permissionStrictPolicy,
std::vector<std::string> packageFiles)
: Logger(logger)
, OutputName(std::move(outputName))
@@ -94,6 +97,8 @@
, PostInst(std::move(postInst))
, GenPostRm(genPostRm)
, PostRm(std::move(postRm))
+ , GenTriggers(genTriggers)
+ , Triggers(std::move(triggers))
, ControlExtra(controlExtra)
, PermissionStrictPolicy(permissionStrictPolicy)
, PackageFiles(std::move(packageFiles))
@@ -206,9 +211,9 @@
<< filename_data_tar << "\" for writing" << std::endl);
return false;
}
- cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType,
- this->DebianArchiveType, this->CompressionLevel,
- static_cast<int>(this->NumThreads));
+ cmArchiveWrite data_tar(
+ fileStream_data_tar, this->TarCompressionType, this->DebianArchiveType,
+ "UTF-8", this->CompressionLevel, static_cast<int>(this->NumThreads));
if (!data_tar.Open()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error opening the archive \""
@@ -297,7 +302,7 @@
cmGeneratedFileStream out;
out.Open(md5filename, false, true);
- std::string topLevelWithTrailingSlash = cmStrCat(this->TemporaryDir, '/');
+ std::string topLevelWithTrailingSlash = cmStrCat(this->WorkDir, '/');
for (std::string const& file : this->PackageFiles) {
// hash only regular files
if (cmSystemTools::FileIsDirectory(file) ||
@@ -339,7 +344,8 @@
return false;
}
cmArchiveWrite control_tar(fileStream_control_tar, this->TarCompressionType,
- this->DebianArchiveType, this->CompressionLevel);
+ this->DebianArchiveType, "UTF-8",
+ this->CompressionLevel);
if (!control_tar.Open()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error opening the archive \""
@@ -429,14 +435,28 @@
control_tar.SetPermissions(permission644);
}
+ if (this->GenTriggers) {
+ if (!control_tar.Add(this->Triggers, this->WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"triggers\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
+ return false;
+ }
+ }
+
// for the other files, we use
// -either the original permission on the files
// -either a permission strictly defined by the Debian policies
if (this->ControlExtra) {
// permissions are now controlled by the original file permissions
- static char const* strictFiles[] = { "config", "postinst", "postrm",
- "preinst", "prerm" };
+ static char const* strictFiles[] = { "config", "postinst", "postrm",
+ "preinst", "prerm", "triggers" };
std::set<std::string> setStrictFiles(
strictFiles, strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0]));
@@ -837,6 +857,7 @@
std::string const postinst = strGenWDIR + "/postinst";
std::string const postrm = strGenWDIR + "/postrm";
+ std::string const triggers = strGenWDIR + "/triggers";
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) {
cmGeneratedFileStream out;
out.Open(postinst, false, true);
@@ -855,6 +876,11 @@
"\tldconfig\n"
"fi\n";
}
+ if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS")) {
+ cmGeneratedFileStream out;
+ out.Open(triggers, false, true);
+ out << "activate-noawait ldconfig\n";
+ }
DebGenerator gen(
this->Logger, this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"), strGenWDIR,
@@ -866,6 +892,7 @@
this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, gen_shibs,
shlibsfilename, this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST"), postinst,
this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM"), postrm,
+ this->IsOn("GEN_CPACK_DEBIAN_GENERATE_LDCONFIG_TRIGGERS"), triggers,
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"),
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
this->packageFiles);
@@ -920,7 +947,7 @@
this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_LEVEL"),
this->GetOption("CPACK_THREADS"),
this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, false, "",
- false, "", false, "", nullptr,
+ false, "", false, "", false, "", nullptr,
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
this->packageFiles);
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 538222d..551a93e 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -4,7 +4,6 @@
#include <algorithm>
#include <cstdlib>
-#include <cstring>
#include <map>
#include <sstream>
#include <utility>
@@ -88,7 +87,7 @@
"Uninstall Files: " << str.str() << std::endl);
this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str());
std::vector<std::string> dirs;
- this->GetListOfSubdirectories(this->toplevel.c_str(), dirs);
+ this->GetListOfSubdirectories(this->toplevel, dirs);
std::ostringstream dstr;
for (std::string const& dir : dirs) {
std::string componentName;
@@ -376,8 +375,10 @@
}
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", installTypesCode);
- this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS",
- "!insertmacro MUI_PAGE_COMPONENTS");
+ if (!this->IsSet("CPACK_NSIS_IGNORE_COMPONENTS_PAGE")) {
+ this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS",
+ "!insertmacro MUI_PAGE_COMPONENTS");
+ }
this->SetOptionIfNotSet("CPACK_NSIS_FULL_INSTALL", "");
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", componentCode);
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", sectionList);
@@ -677,18 +678,17 @@
}
bool cmCPackNSISGenerator::GetListOfSubdirectories(
- char const* topdir, std::vector<std::string>& dirs)
+ std::string const& topdir, std::vector<std::string>& dirs)
{
cmsys::Directory dir;
dir.Load(topdir);
for (unsigned long i = 0; i < dir.GetNumberOfFiles(); ++i) {
- char const* fileName = dir.GetFile(i);
- if (strcmp(fileName, ".") != 0 && strcmp(fileName, "..") != 0) {
- std::string const fullPath =
- std::string(topdir).append("/").append(fileName);
+ std::string const& fileName = dir.GetFileName(i);
+ if (fileName != "." && fileName != "..") {
+ std::string const fullPath = cmStrCat(topdir, '/', fileName);
if (cmsys::SystemTools::FileIsDirectory(fullPath) &&
!cmsys::SystemTools::FileIsSymlink(fullPath)) {
- if (!this->GetListOfSubdirectories(fullPath.c_str(), dirs)) {
+ if (!this->GetListOfSubdirectories(fullPath, dirs)) {
return false;
}
}
diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h
index 5aca90d..d9a37bc 100644
--- a/Source/CPack/cmCPackNSISGenerator.h
+++ b/Source/CPack/cmCPackNSISGenerator.h
@@ -44,7 +44,7 @@
char const* GetOutputExtension() override { return ".exe"; }
char const* GetOutputPostfix() override { return "win32"; }
- bool GetListOfSubdirectories(char const* dir,
+ bool GetListOfSubdirectories(std::string const& dir,
std::vector<std::string>& dirs);
enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir()
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index aafa92b..cfa9a3b 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -85,18 +85,9 @@
std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD");
- std::string identityName;
- if (cmValue n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) {
- identityName = n;
- }
- std::string keychainPath;
- if (cmValue p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) {
- keychainPath = p;
- }
- std::string identifier;
- if (cmValue i = this->GetOption("CPACK_PRODUCTBUILD_IDENTIFIER")) {
- identifier = i;
- }
+ cmValue identityName = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME");
+ cmValue keychainPath = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH");
+ cmValue identifier = this->GetOption("CPACK_PRODUCTBUILD_IDENTIFIER");
pkgCmd << productbuild << " --distribution \"" << packageDirFileName
<< "/Contents/distribution.dist\""
@@ -108,16 +99,17 @@
<< resDir
<< "\""
" --version \""
- << version << "\""
- << (identifier.empty()
- ? std::string{}
- : cmStrCat(" --identifier \"", identifier, '"'))
- << (identityName.empty() ? std::string{}
- : cmStrCat(" --sign \"", identityName, '"'))
- << (keychainPath.empty()
- ? std::string{}
- : cmStrCat(" --keychain \"", keychainPath, '"'))
- << " \"" << packageFileNames[0] << '"';
+ << version << '"';
+ if (identifier) {
+ pkgCmd << " --identifier \"" << identifier << '"';
+ }
+ if (identityName) {
+ pkgCmd << " --sign \"" << identityName << '"';
+ }
+ if (keychainPath) {
+ pkgCmd << " --keychain \"" << keychainPath << '"';
+ }
+ pkgCmd << " \"" << packageFileNames[0] << '"';
// Run ProductBuild
return RunProductBuild(pkgCmd.str());
@@ -205,10 +197,10 @@
// then copy them into the script directory and make
// them executable
if (preflight) {
- this->CopyInstallScript(scriptDir, preflight, "preinstall");
+ this->CopyInstallScript(scriptDir, *preflight, "preinstall");
}
if (postflight) {
- this->CopyInstallScript(scriptDir, postflight, "postinstall");
+ this->CopyInstallScript(scriptDir, *postflight, "postinstall");
}
// The command that will be used to run ProductBuild
@@ -216,7 +208,7 @@
std::string pkgId;
if (cmValue n = this->GetOption("CPACK_PRODUCTBUILD_IDENTIFIER")) {
- pkgId = n;
+ pkgId = *n;
} else {
pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
this->GetOption("CPACK_PACKAGE_NAME"));
@@ -228,14 +220,8 @@
std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD");
- std::string identityName;
- if (cmValue n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) {
- identityName = n;
- }
- std::string keychainPath;
- if (cmValue p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) {
- keychainPath = p;
- }
+ cmValue identityName = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME");
+ cmValue keychainPath = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH");
pkgCmd << pkgbuild << " --root \"" << packageDir
<< "\""
@@ -248,16 +234,17 @@
" --version \""
<< version
<< "\""
- " --install-location \"/\""
- << (identityName.empty() ? std::string{}
- : cmStrCat(" --sign \"", identityName, '"'))
- << (keychainPath.empty()
- ? std::string{}
- : cmStrCat(" --keychain \"", keychainPath, '"'))
- << " \"" << packageFile << '"';
+ " --install-location \"/\"";
+ if (identityName) {
+ pkgCmd << " --sign \"" << identityName << '"';
+ }
+ if (keychainPath) {
+ pkgCmd << " --keychain \"" << keychainPath << '"';
+ }
+ pkgCmd << " \"" << packageFile << '"';
if (component && !component->Plist.empty()) {
- pkgCmd << " --component-plist \"" << component->Plist << "\"";
+ pkgCmd << " --component-plist \"" << component->Plist << '"';
}
// Run ProductBuild
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 3a79367..1149fb2 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -199,7 +199,8 @@
CommandArgument::setToValue(cpackProjectPatch) },
CommandArgument{ "--vendor", CommandArgument::Values::One,
CommandArgument::setToValue(cpackProjectVendor) },
- CommandArgument{ "--preset", CommandArgument::Values::One,
+ CommandArgument{ "--preset", "No preset specified for --preset",
+ CommandArgument::Values::One,
CommandArgument::setToValue(preset) },
CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
CommandArgument::setToTrue(listPresets) },
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 71c9e3f..c7e7c3d 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -465,6 +465,9 @@
xml.StartElement("Build");
xml.Element("StartDateTime", this->StartBuild);
xml.Element("StartBuildTime", this->StartBuildTime);
+ xml.Element("SourceDirectory",
+ this->CTest->GetCTestConfiguration("SourceDirectory"));
+ xml.Element("BinaryDirectory", this->CTest->GetBinaryDir());
xml.Element("BuildCommand", this->GetMakeCommand());
}
@@ -511,7 +514,7 @@
launchDir.Load(this->CTestLaunchDir);
unsigned long n = launchDir.GetNumberOfFiles();
for (unsigned long i = 0; i < n; ++i) {
- char const* fname = launchDir.GetFile(i);
+ std::string const& fname = launchDir.GetFileName(i);
if (this->IsLaunchedErrorFile(fname) && numErrorsAllowed) {
numErrorsAllowed--;
fragments.insert(cmStrCat(this->CTestLaunchDir, '/', fname));
@@ -616,7 +619,7 @@
if (!targets_dir.FileIsDirectory(i)) {
continue;
}
- std::string target_name = targets_dir.GetFile(i);
+ std::string const& target_name = targets_dir.GetFileName(i);
if (target_name == "." || target_name == "..") {
continue;
}
@@ -696,14 +699,14 @@
this->CTest->EndXML(xml);
}
-bool cmCTestBuildHandler::IsLaunchedErrorFile(char const* fname)
+bool cmCTestBuildHandler::IsLaunchedErrorFile(cm::string_view fname)
{
// error-{hash}.xml
return (cmHasLiteralPrefix(fname, "error-") &&
cmHasLiteralSuffix(fname, ".xml"));
}
-bool cmCTestBuildHandler::IsLaunchedWarningFile(char const* fname)
+bool cmCTestBuildHandler::IsLaunchedWarningFile(cm::string_view fname)
{
// warning-{hash}.xml
return (cmHasLiteralPrefix(fname, "warning-") &&
@@ -949,7 +952,7 @@
launchDir.Load(this->CTestLaunchDir);
unsigned long n = launchDir.GetNumberOfFiles();
for (unsigned long i = 0; i < n; ++i) {
- char const* fname = launchDir.GetFile(i);
+ std::string const& fname = launchDir.GetFileName(i);
if (cmHasLiteralSuffix(fname, ".xml")) {
launcherXMLFound = true;
break;
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 2b8feec..470d3f9 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -11,6 +11,8 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmsys/RegularExpression.hxx"
#include "cmCTestGenericHandler.h"
@@ -86,8 +88,8 @@
void GenerateXMLLogScraped(cmXMLWriter& xml);
void GenerateInstrumentationXML(cmXMLWriter& xml);
void GenerateXMLFooter(cmXMLWriter& xml, cmDuration elapsed_build_time);
- bool IsLaunchedErrorFile(char const* fname);
- bool IsLaunchedWarningFile(char const* fname);
+ bool IsLaunchedErrorFile(cm::string_view fname);
+ bool IsLaunchedWarningFile(cm::string_view fname);
std::string StartBuild;
std::string EndBuild;
diff --git a/Source/CTest/cmCTestDiscoverTests.cxx b/Source/CTest/cmCTestDiscoverTests.cxx
new file mode 100644
index 0000000..95a97a1
--- /dev/null
+++ b/Source/CTest/cmCTestDiscoverTests.cxx
@@ -0,0 +1,163 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmCTestDiscoverTests.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdlib>
+#include <iterator>
+#include <string>
+#include <vector>
+
+#include <cmsys/RegularExpression.hxx>
+
+#include "cmArgumentParserTypes.h"
+#include "cmCTestTestHandler.h"
+#include "cmDuration.h"
+#include "cmEnvironment.h"
+#include "cmExecutionStatus.h"
+#include "cmList.h"
+#include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTestDiscovery.h"
+
+namespace {
+
+struct DiscoveryProperties
+{
+ DiscoveryProperties(std::vector<std::string> const& props);
+
+ std::vector<std::string> Environment;
+ std::vector<std::string> EnvironmentModification;
+ cmDuration Timeout = cmDuration(5.0);
+ std::string WorkingDirectory;
+};
+
+DiscoveryProperties::DiscoveryProperties(std::vector<std::string> const& props)
+{
+ for (std::size_t i = 0; i < props.size(); i += 2) {
+ auto const& key = props[i];
+ auto const& val = props[i + 1];
+ if (key == "ENVIRONMENT") {
+ cmExpandList(val, this->Environment);
+ } else if (key == "ENVIRONMENT_MODIFICATION") {
+ cmExpandList(val, this->EnvironmentModification);
+ } else if (key == "TIMEOUT") {
+ this->Timeout = cmDuration(atof(val.c_str()));
+ } else if (key == "WORKING_DIRECTORY") {
+ this->WorkingDirectory = val;
+ }
+ }
+}
+
+std::string AddAnchors(std::string str)
+{
+ if (str.empty() || str.front() != '^') {
+ str.insert(str.begin(), '^');
+ }
+ if (str.size() < 2 || str.back() != '$') {
+ str.push_back('$');
+ }
+ return str;
+}
+
+class RegexReplacer
+{
+public:
+ RegexReplacer(cmsys::RegularExpression& regex)
+ : RegEx(regex)
+ {
+ }
+
+ std::string operator()(std::string str)
+ {
+ for (int i = 0; i <= this->RegEx.num_groups(); ++i) {
+ cmsys::SystemTools::ReplaceString(str, cmStrCat('\\', i),
+ this->RegEx.match(i));
+ }
+ return str;
+ }
+
+private:
+ cmsys::RegularExpression& RegEx;
+};
+
+} // namespace
+
+bool cmCTestDiscoverTests(cmTestDiscoveryArgs const& args,
+ cmCTestTestHandler* handler,
+ cmExecutionStatus& status)
+{
+ cmsys::RegularExpression re;
+ if (!re.compile(AddAnchors(args.DiscoveryMatch))) {
+ std::string e = "DISCOVERY_MATCH failed to compile regex \"" +
+ args.DiscoveryMatch + "\".";
+ status.SetError(e);
+ return false;
+ }
+
+ auto const props = DiscoveryProperties{ args.DiscoveryProperties };
+
+ auto env = cmEnvironment{ cmSystemTools::GetEnvironmentVariables() };
+ env.Update(props.Environment);
+ if (!props.EnvironmentModification.empty()) {
+ auto diff = cmEnvironmentModification{};
+ if (!diff.Add(props.EnvironmentModification)) {
+ return false;
+ }
+ diff.ApplyTo(env);
+ }
+
+ auto runCommand = std::vector<std::string>(args.Command);
+ runCommand.reserve(runCommand.size() + args.DiscoveryArgs.size());
+ std::copy(args.DiscoveryArgs.begin(), args.DiscoveryArgs.end(),
+ std::back_inserter(runCommand));
+
+ std::string stdOut;
+ std::string stdErr;
+ bool const res = cmSystemTools::RunSingleCommand(
+ runCommand, &stdOut, &stdErr, nullptr, props.WorkingDirectory.c_str(),
+ cmSystemTools::OUTPUT_NONE, props.Timeout, cmProcessOutput::Auto,
+ env.GetVariables());
+ if (!res) {
+ status.SetError(cmStrCat(" failed to run command: ",
+ cmSystemTools::PrintSingleCommand(runCommand),
+ "\n", stdErr));
+ return false;
+ }
+
+ auto replace = RegexReplacer{ re };
+
+ std::vector<std::string> lines;
+ cmSystemTools::Split(stdOut, lines);
+ for (auto const& line : lines) {
+ if (!re.find(line)) {
+ continue;
+ }
+
+ auto const testName = replace(args.TestName);
+ auto testArgs = std::vector<std::string>{ testName };
+ testArgs.reserve(1 + args.Command.size() + args.TestArgs.size());
+ std::copy(args.Command.begin(), args.Command.end(),
+ std::back_inserter(testArgs));
+ std::transform(args.TestArgs.begin(), args.TestArgs.end(),
+ std::back_inserter(testArgs), replace);
+
+ if (!handler->AddTest(testArgs)) {
+ return false;
+ }
+
+ auto testProperties = std::vector<std::string>{ testName, "PROPERTIES" };
+ testProperties.reserve(2 + args.TestProperties.size());
+ for (std::size_t i = 0; i < args.TestProperties.size(); i += 2) {
+ testProperties.push_back(args.TestProperties[i]);
+ testProperties.push_back(replace(args.TestProperties[i + 1]));
+ }
+ if (!handler->SetTestsProperties(testProperties)) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/Source/CTest/cmCTestDiscoverTests.h b/Source/CTest/cmCTestDiscoverTests.h
new file mode 100644
index 0000000..8de7d7e
--- /dev/null
+++ b/Source/CTest/cmCTestDiscoverTests.h
@@ -0,0 +1,13 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+struct cmTestDiscoveryArgs;
+class cmCTestTestHandler;
+class cmExecutionStatus;
+
+bool cmCTestDiscoverTests(cmTestDiscoveryArgs const& args,
+ cmCTestTestHandler* handler,
+ cmExecutionStatus& status);
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
index 3fba37e..edcb1ef 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
@@ -4,6 +4,7 @@
#include "cmsys/Directory.hxx"
+#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -21,7 +22,7 @@
// Make sure that CMakeCache.txt is deleted last.
for (unsigned long i = 0; i < directory.GetNumberOfFiles(); ++i) {
- std::string path = directory.GetFile(i);
+ std::string const& path = directory.GetFileName(i);
if (path == "." || path == ".." || path == "CMakeCache.txt") {
continue;
@@ -97,7 +98,7 @@
if (!EmptyBinaryDirectory(args[0], err)) {
cmMakefile& mf = status.GetMakefile();
mf.GetMessenger()->DisplayMessage(
- MessageType::FATAL_ERROR,
+ MessageType::FATAL_ERROR, cmDiagnostics::CMD_NONE,
cmStrCat("Did not remove the binary directory:\n ", args[0],
"\nbecause:\n ", err),
mf.GetBacktrace());
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 97b1d16..c5e7ce1 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -21,6 +21,7 @@
#include "cmCTestMemCheckHandler.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmDuration.h"
+#include "cmEnvironment.h"
#include "cmInstrumentation.h"
#include "cmProcess.h"
#include "cmStringAlgorithms.h"
@@ -707,6 +708,12 @@
testCommand += "\"";
this->Arguments.push_back(*j);
}
+ // Append passthrough arguments from ctest command line (after --)
+ for (std::string const& arg :
+ this->TestHandler->TestOptions.TestPassthroughArguments) {
+ testCommand = cmStrCat(std::move(testCommand), " \"", arg, '"');
+ this->Arguments.push_back(arg);
+ }
this->TestResult.FullCommandLine = testCommand;
// Print the test command in verbose mode
@@ -853,62 +860,36 @@
this->TestHandler->GetQuiet());
}
- cmSystemTools::SaveRestoreEnvironment sre;
- std::ostringstream envMeasurement;
+ // Record the original environment before modifying it
+ auto const originalEnvironment =
+ cmEnvironment{ cmSystemTools::GetEnvironmentVariables() };
- // We split processing ENVIRONMENT and ENVIRONMENT_MODIFICATION into two
- // phases to ensure that MYVAR=reset: in the latter phase resets to the
- // former phase's settings, rather than to the original environment.
- if (!this->TestProperties->Environment.empty()) {
- cmSystemTools::EnvDiff diff;
- diff.AppendEnv(this->TestProperties->Environment);
- diff.ApplyToCurrentEnv(&envMeasurement);
- }
-
+ auto env = originalEnvironment;
+ env.Update(this->TestProperties->Environment);
if (!this->TestProperties->EnvironmentModification.empty()) {
- cmSystemTools::EnvDiff diff;
- bool env_ok = true;
-
- for (auto const& envmod : this->TestProperties->EnvironmentModification) {
- env_ok &= diff.ParseOperation(envmod);
- }
-
- if (!env_ok) {
+ auto diff = cmEnvironmentModification{};
+ if (!diff.Add(this->TestProperties->EnvironmentModification)) {
return false;
}
-
- diff.ApplyToCurrentEnv(&envMeasurement);
+ diff.ApplyTo(env);
}
if (this->UseAllocatedResources) {
- std::vector<std::string> envLog;
- this->SetupResourcesEnvironment(&envLog);
- for (auto const& var : envLog) {
- envMeasurement << var << std::endl;
- }
+ this->SetupResourcesEnvironment(env);
} else {
- cmSystemTools::UnsetEnv("CTEST_RESOURCE_GROUP_COUNT");
- // Signify that this variable is being actively unset
- envMeasurement << "#CTEST_RESOURCE_GROUP_COUNT=" << std::endl;
+ env.UnPutEnv("CTEST_RESOURCE_GROUP_COUNT");
}
- this->TestResult.Environment = envMeasurement.str();
- // Remove last newline
- this->TestResult.Environment.erase(this->TestResult.Environment.length() -
- 1);
-
+ this->TestProcess->SetEnvironment(env.GetVariables());
+ this->TestResult.Environment = env.RecordDifference(originalEnvironment);
return this->TestProcess->StartProcess(*this->MultiTestHandler.Loop,
&this->TestProperties->Affinity);
}
-void cmCTestRunTest::SetupResourcesEnvironment(std::vector<std::string>* log)
+void cmCTestRunTest::SetupResourcesEnvironment(cmEnvironment& env)
{
- std::string processCount =
- cmStrCat("CTEST_RESOURCE_GROUP_COUNT=", this->AllocatedResources.size());
- cmSystemTools::PutEnv(processCount);
- if (log) {
- log->emplace_back(std::move(processCount));
- }
+ env.PutEnv(
+ cmStrCat("CTEST_RESOURCE_GROUP_COUNT=", this->AllocatedResources.size()));
std::size_t i = 0;
for (auto const& process : this->AllocatedResources) {
@@ -933,15 +914,9 @@
firstName = false;
var += cmStrCat("id:", it2.Id, ",slots:", it2.Slots);
}
- cmSystemTools::PutEnv(var);
- if (log) {
- log->push_back(var);
- }
+ env.PutEnv(var);
}
- cmSystemTools::PutEnv(resourceList);
- if (log) {
- log->push_back(resourceList);
- }
+ env.PutEnv(resourceList);
++i;
}
}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 3905dab..37ec24a 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -16,6 +16,8 @@
#include "cmCTestTestHandler.h"
#include "cmProcess.h"
+class cmEnvironment;
+
/** \class cmRunTest
* \brief represents a single test to be run
*
@@ -113,7 +115,7 @@
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
- void SetupResourcesEnvironment(std::vector<std::string>* log = nullptr);
+ void SetupResourcesEnvironment(cmEnvironment& env);
// Returns "completed/total Test #Index: "
std::string GetTestPrefix(size_t completed, size_t total) const;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 5c6679e..65957af 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -15,6 +15,7 @@
#include <ratio>
#include <set>
#include <sstream>
+#include <string>
#include <utility>
#ifndef _WIN32
@@ -33,7 +34,9 @@
#include "cm_utf8.h"
+#include "cmArgumentParser.h"
#include "cmCTest.h"
+#include "cmCTestDiscoverTests.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestResourceGroupsLexerHelper.h"
#include "cmCTestTestMeasurementXMLParser.h"
@@ -49,6 +52,7 @@
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTestDiscovery.h"
#include "cmTimestamp.h"
#include "cmValue.h"
#include "cmWorkingDirectory.h"
@@ -184,6 +188,34 @@
return this->TestHandler->AddTest(args);
}
+class cmCTestDiscoverTestsCommand : public cmCTestCommand
+{
+public:
+ using cmCTestCommand::cmCTestCommand;
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) override;
+};
+
+bool cmCTestDiscoverTestsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus& status)
+{
+ using Arguments = cmTestDiscoveryArgs;
+ static auto const parser = cmTestDiscoveryParser<Arguments>();
+
+ auto unparsed = std::vector<std::string>{};
+ Arguments const arguments = parser.Parse(args, &unparsed);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
+
+ if (!unparsed.empty()) {
+ status.SetError(" given unknown argument \"" + unparsed.front() + "\".");
+ return false;
+ }
+
+ return cmCTestDiscoverTests(arguments, this->TestHandler, status);
+}
+
class cmCTestSetTestsPropertiesCommand : public cmCTestCommand
{
public:
@@ -359,7 +391,7 @@
<< cmSystemTools::GetLogicalWorkingDirectory()
<< std::endl,
this->Quiet);
- if (!this->PreProcessHandler()) {
+ if (!this->CTest->GetShowOnly() && !this->PreProcessHandler()) {
return -1;
}
@@ -428,7 +460,7 @@
return 1;
}
- if (!this->PostProcessHandler()) {
+ if (!this->CTest->GetShowOnly() && !this->PostProcessHandler()) {
this->LogFile = nullptr;
return -1;
}
@@ -547,13 +579,21 @@
} else {
failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED);
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::endl
- << passColorCode << std::lround(percent) << "% tests passed"
- << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
- << ", " << failedColorCode << failed.size() << " tests failed"
- << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
- << " out of " << total << std::endl);
+ if (failed.empty()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
+ << passColorCode << std::lround(percent) << "% tests passed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << " out of " << total << std::endl);
+ } else {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
+ << passColorCode << std::lround(percent) << "% tests passed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << ", " << failedColorCode << failed.size() << " tests failed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << " out of " << total << std::endl);
+ }
if ((!this->CTest->GetLabelsForSubprojects().empty() &&
this->CTest->GetSubprojectSummary())) {
this->PrintLabelOrSubprojectSummary(true);
@@ -1772,6 +1812,10 @@
// Add handler for ADD_TEST
cm.GetState()->AddBuiltinCommand("add_test", cmCTestAddTestCommand(this));
+ // Add handler for DISCOVER_TESTS
+ cm.GetState()->AddBuiltinCommand("discover_tests",
+ cmCTestDiscoverTestsCommand(this));
+
// Add handler for SUBDIRS
cm.GetState()->AddBuiltinCommand("subdirs", cmCTestSubdirCommand);
@@ -1933,15 +1977,11 @@
int numFiles =
static_cast<int>(cmsys::Directory::GetNumberOfFilesInDirectory(dirName));
- std::string pattern = "LastTestsFailed";
std::string logName;
for (int i = 0; i < numFiles; ++i) {
- std::string fileName = directory.GetFile(i);
- // bcc crashes if we attempt a normal substring comparison,
- // hence the following workaround
- std::string fileNameSubstring = fileName.substr(0, pattern.length());
- if (fileNameSubstring != pattern) {
+ std::string const& fileName = directory.GetFileName(i);
+ if (!cmHasLiteralPrefix(fileName, "LastTestsFailed")) {
continue;
}
if (logName.empty()) {
@@ -2441,36 +2481,13 @@
this->ExcludeTestsRegularExpression.find(testname)) {
return true;
}
- if (this->MemCheck) {
- std::vector<std::string>::iterator it;
- bool found = false;
- for (it = this->CustomTestsIgnore.begin();
- it != this->CustomTestsIgnore.end(); ++it) {
- if (*it == testname) {
- found = true;
- break;
- }
- }
- if (found) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Ignore memcheck: " << *it << std::endl, this->Quiet);
- return true;
- }
- } else {
- std::vector<std::string>::iterator it;
- bool found = false;
- for (it = this->CustomTestsIgnore.begin();
- it != this->CustomTestsIgnore.end(); ++it) {
- if (*it == testname) {
- found = true;
- break;
- }
- }
- if (found) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Ignore test: " << *it << std::endl, this->Quiet);
- return true;
- }
+
+ if (cm::contains(this->CustomTestsIgnore, testname)) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Ignore " << (this->MemCheck ? "memcheck" : "test")
+ << ": " << testname << std::endl,
+ this->Quiet);
+ return true;
}
cmCTestTestProperties test;
@@ -2487,7 +2504,7 @@
this->ExcludeTestsRegularExpression.find(testname)))) {
test.IsInBasedOnREOptions = false;
}
- this->TestList.push_back(test);
+ this->TestList.push_back(std::move(test));
return true;
}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 3a2e556..4d4dbb8 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -55,6 +55,8 @@
std::string ExcludeTestListFile;
std::string ResourceSpecFile;
std::string JUnitXMLFileName;
+
+ std::vector<std::string> TestPassthroughArguments;
};
/** \class cmCTestTestHandler
diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx
index 07fa478..44dcc6b 100644
--- a/Source/CTest/cmParseCacheCoverage.cxx
+++ b/Source/CTest/cmParseCacheCoverage.cxx
@@ -31,7 +31,7 @@
unsigned int i;
numf = dir.GetNumberOfFiles();
for (i = 0; i < numf; i++) {
- std::string file = dir.GetFile(i);
+ std::string const& file = dir.GetFileName(i);
if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
std::string path = cmStrCat(d, '/', file);
if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") {
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index c11be30..7ca5fe8 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -29,7 +29,7 @@
unsigned int i;
numf = dir.GetNumberOfFiles();
for (i = 0; i < numf; i++) {
- std::string file = dir.GetFile(i);
+ std::string const& file = dir.GetFileName(i);
if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
std::string path = cmStrCat(d, '/', file);
if (cmSystemTools::GetFilenameLastExtension(path) == ".mcov") {
diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx
index 14c9fe8..0bc98d7 100644
--- a/Source/CTest/cmParsePHPCoverage.cxx
+++ b/Source/CTest/cmParsePHPCoverage.cxx
@@ -210,7 +210,7 @@
unsigned int i;
numf = dir.GetNumberOfFiles();
for (i = 0; i < numf; i++) {
- std::string file = dir.GetFile(i);
+ std::string const& file = dir.GetFileName(i);
if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
std::string path = cmStrCat(d, '/', file);
if (!this->ReadPHPData(path.c_str())) {
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 0610672..d0e3d0c 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -35,19 +35,24 @@
cmProcess::~cmProcess() = default;
-void cmProcess::SetCommand(std::string const& command)
+void cmProcess::SetCommand(std::string command)
{
- this->Command = command;
+ this->Command = std::move(command);
}
-void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
+void cmProcess::SetCommandArguments(std::vector<std::string> args)
{
- this->Arguments = args;
+ this->Arguments = std::move(args);
}
-void cmProcess::SetWorkingDirectory(std::string const& dir)
+void cmProcess::SetEnvironment(std::vector<std::string> env)
{
- this->WorkingDirectory = dir;
+ this->Environment = std::move(env);
+}
+
+void cmProcess::SetWorkingDirectory(std::string dir)
+{
+ this->WorkingDirectory = std::move(dir);
}
bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity)
@@ -128,6 +133,15 @@
#else
static_cast<void>(affinity);
#endif
+ if (!this->Environment.empty()) {
+ this->Env.clear();
+ this->Env.reserve(this->Environment.size() + 1);
+ for (auto const& var : this->Environment) {
+ this->Env.push_back(var.c_str());
+ }
+ this->Env.push_back(nullptr);
+ options.env = const_cast<char**>(this->Env.data());
+ }
status =
uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB);
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index a4704b4..d475dd3 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -34,9 +34,10 @@
public:
explicit cmProcess(std::unique_ptr<cmCTestRunTest> runner);
~cmProcess();
- void SetCommand(std::string const& command);
- void SetCommandArguments(std::vector<std::string> const& arg);
- void SetWorkingDirectory(std::string const& dir);
+ void SetCommand(std::string command);
+ void SetCommandArguments(std::vector<std::string> arg);
+ void SetEnvironment(std::vector<std::string> env);
+ void SetWorkingDirectory(std::string dir);
void SetStopTimeout(cmDuration t) { this->StopTimeout = t; }
void SetTimeout(cmDuration t) { this->Timeout = t; }
void ChangeTimeout(cmDuration t);
@@ -161,6 +162,8 @@
std::string WorkingDirectory;
std::vector<std::string> Arguments;
std::vector<char const*> ProcessArgs;
+ std::vector<std::string> Environment;
+ std::vector<char const*> Env;
int Id;
int64_t ExitValue;
Termination TerminationStyle = Termination::Normal;
diff --git a/Source/Checks/Curses/CMakeLists.txt b/Source/Checks/Curses/CMakeLists.txt
index c7b8e5f..2854172 100644
--- a/Source/Checks/Curses/CMakeLists.txt
+++ b/Source/Checks/Curses/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.13...4.1 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.13...4.2 FATAL_ERROR)
project(CheckCurses C)
set(CURSES_NEED_NCURSES TRUE)
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
index b63fbf4..d30d5cf 100644
--- a/Source/LexerParser/cmExprParser.cxx
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -90,7 +90,6 @@
#include <stdlib.h>
#include <string.h>
-#include <stdexcept>
/*-------------------------------------------------------------------------*/
#define YYDEBUG 1
@@ -126,7 +125,7 @@
# pragma diag_suppress 550 /* variable set but never used */
#endif
-#line 130 "cmExprParser.cxx"
+#line 129 "cmExprParser.cxx"
# ifndef YY_CAST
# ifdef __cplusplus
@@ -568,9 +567,9 @@
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 87, 87, 92, 95, 100, 103, 108, 111, 116,
- 119, 122, 127, 130, 133, 138, 141, 144, 150, 158,
- 161, 164, 167, 172, 175
+ 0, 86, 86, 91, 94, 99, 102, 107, 110, 115,
+ 118, 122, 128, 131, 135, 141, 144, 148, 152, 158,
+ 161, 164, 168, 173, 176
};
#endif
@@ -1431,73 +1430,74 @@
switch (yyn)
{
case 2: /* start: exp */
-#line 87 "cmExprParser.y"
+#line 86 "cmExprParser.y"
{
cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
}
-#line 1439 "cmExprParser.cxx"
+#line 1438 "cmExprParser.cxx"
break;
case 3: /* exp: bitwiseor */
-#line 92 "cmExprParser.y"
+#line 91 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1447 "cmExprParser.cxx"
+#line 1446 "cmExprParser.cxx"
break;
case 4: /* exp: exp exp_OR bitwiseor */
-#line 95 "cmExprParser.y"
+#line 94 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
}
-#line 1455 "cmExprParser.cxx"
+#line 1454 "cmExprParser.cxx"
break;
case 5: /* bitwiseor: bitwisexor */
-#line 100 "cmExprParser.y"
+#line 99 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1463 "cmExprParser.cxx"
+#line 1462 "cmExprParser.cxx"
break;
case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */
-#line 103 "cmExprParser.y"
+#line 102 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
}
-#line 1471 "cmExprParser.cxx"
+#line 1470 "cmExprParser.cxx"
break;
case 7: /* bitwisexor: bitwiseand */
-#line 108 "cmExprParser.y"
+#line 107 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1479 "cmExprParser.cxx"
+#line 1478 "cmExprParser.cxx"
break;
case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */
-#line 111 "cmExprParser.y"
+#line 110 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
}
-#line 1487 "cmExprParser.cxx"
+#line 1486 "cmExprParser.cxx"
break;
case 9: /* bitwiseand: shift */
-#line 116 "cmExprParser.y"
+#line 115 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1495 "cmExprParser.cxx"
+#line 1494 "cmExprParser.cxx"
break;
case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */
-#line 119 "cmExprParser.y"
+#line 118 "cmExprParser.y"
{
- (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->ShL((yyvsp[-2].Number), (yyvsp[0].Number));
}
#line 1503 "cmExprParser.cxx"
break;
@@ -1505,69 +1505,69 @@
case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */
#line 122 "cmExprParser.y"
{
- (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->ShR((yyvsp[-2].Number), (yyvsp[0].Number));
}
-#line 1511 "cmExprParser.cxx"
+#line 1512 "cmExprParser.cxx"
break;
case 12: /* shift: term */
-#line 127 "cmExprParser.y"
+#line 128 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1519 "cmExprParser.cxx"
+#line 1520 "cmExprParser.cxx"
break;
case 13: /* shift: shift exp_PLUS term */
-#line 130 "cmExprParser.y"
+#line 131 "cmExprParser.y"
{
- (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->Add((yyvsp[-2].Number), (yyvsp[0].Number));
}
-#line 1527 "cmExprParser.cxx"
+#line 1529 "cmExprParser.cxx"
break;
case 14: /* shift: shift exp_MINUS term */
-#line 133 "cmExprParser.y"
+#line 135 "cmExprParser.y"
{
- (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->Sub((yyvsp[-2].Number), (yyvsp[0].Number));
}
-#line 1535 "cmExprParser.cxx"
+#line 1538 "cmExprParser.cxx"
break;
case 15: /* term: unary */
-#line 138 "cmExprParser.y"
+#line 141 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1543 "cmExprParser.cxx"
+#line 1546 "cmExprParser.cxx"
break;
case 16: /* term: term exp_TIMES unary */
-#line 141 "cmExprParser.y"
+#line 144 "cmExprParser.y"
{
- (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->Mul((yyvsp[-2].Number), (yyvsp[0].Number));
}
-#line 1551 "cmExprParser.cxx"
+#line 1555 "cmExprParser.cxx"
break;
case 17: /* term: term exp_DIVIDE unary */
-#line 144 "cmExprParser.y"
+#line 148 "cmExprParser.y"
{
- if (yyvsp[0].Number == 0) {
- throw std::overflow_error("divide by zero");
- }
- (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->Div((yyvsp[-2].Number), (yyvsp[0].Number));
}
-#line 1562 "cmExprParser.cxx"
+#line 1564 "cmExprParser.cxx"
break;
case 18: /* term: term exp_MOD unary */
-#line 150 "cmExprParser.y"
+#line 152 "cmExprParser.y"
{
- if (yyvsp[0].Number == 0) {
- throw std::overflow_error("modulo by zero");
- }
- (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->Mod((yyvsp[-2].Number), (yyvsp[0].Number));
}
#line 1573 "cmExprParser.cxx"
break;
@@ -1591,37 +1591,38 @@
case 21: /* unary: exp_MINUS unary */
#line 164 "cmExprParser.y"
{
- (yyval.Number) = - (yyvsp[0].Number);
+ (yyval.Number) = cmExpr_yyget_extra(yyscanner)
+ ->Neg((yyvsp[0].Number));
}
-#line 1597 "cmExprParser.cxx"
+#line 1598 "cmExprParser.cxx"
break;
case 22: /* unary: exp_NOT unary */
-#line 167 "cmExprParser.y"
+#line 168 "cmExprParser.y"
{
(yyval.Number) = ~ (yyvsp[0].Number);
}
-#line 1605 "cmExprParser.cxx"
+#line 1606 "cmExprParser.cxx"
break;
case 23: /* factor: exp_NUMBER */
-#line 172 "cmExprParser.y"
+#line 173 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1613 "cmExprParser.cxx"
+#line 1614 "cmExprParser.cxx"
break;
case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */
-#line 175 "cmExprParser.y"
+#line 176 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-1].Number);
}
-#line 1621 "cmExprParser.cxx"
+#line 1622 "cmExprParser.cxx"
break;
-#line 1625 "cmExprParser.cxx"
+#line 1626 "cmExprParser.cxx"
default: break;
}
@@ -1845,7 +1846,7 @@
return yyresult;
}
-#line 180 "cmExprParser.y"
+#line 181 "cmExprParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
index 0cb120c..edd3bc5 100644
--- a/Source/LexerParser/cmExprParser.y
+++ b/Source/LexerParser/cmExprParser.y
@@ -15,7 +15,6 @@
#include <stdlib.h>
#include <string.h>
-#include <stdexcept>
/*-------------------------------------------------------------------------*/
#define YYDEBUG 1
@@ -117,10 +116,12 @@
$<Number>$ = $<Number>1;
}
| bitwiseand exp_SHIFTLEFT shift {
- $<Number>$ = $<Number>1 << $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->ShL($<Number>1, $<Number>3);
}
| bitwiseand exp_SHIFTRIGHT shift {
- $<Number>$ = $<Number>1 >> $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->ShR($<Number>1, $<Number>3);
}
shift:
@@ -128,10 +129,12 @@
$<Number>$ = $<Number>1;
}
| shift exp_PLUS term {
- $<Number>$ = $<Number>1 + $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->Add($<Number>1, $<Number>3);
}
| shift exp_MINUS term {
- $<Number>$ = $<Number>1 - $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->Sub($<Number>1, $<Number>3);
}
term:
@@ -139,19 +142,16 @@
$<Number>$ = $<Number>1;
}
| term exp_TIMES unary {
- $<Number>$ = $<Number>1 * $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->Mul($<Number>1, $<Number>3);
}
| term exp_DIVIDE unary {
- if (yyvsp[0].Number == 0) {
- throw std::overflow_error("divide by zero");
- }
- $<Number>$ = $<Number>1 / $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->Div($<Number>1, $<Number>3);
}
| term exp_MOD unary {
- if (yyvsp[0].Number == 0) {
- throw std::overflow_error("modulo by zero");
- }
- $<Number>$ = $<Number>1 % $<Number>3;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->Mod($<Number>1, $<Number>3);
}
unary:
@@ -162,7 +162,8 @@
$<Number>$ = + $<Number>2;
}
| exp_MINUS unary {
- $<Number>$ = - $<Number>2;
+ $<Number>$ = cmExpr_yyget_extra(yyscanner)
+ ->Neg($<Number>2);
}
| exp_NOT unary {
$<Number>$ = ~ $<Number>2;
diff --git a/Source/Modules/CMakeBuildUtilities.cmake b/Source/Modules/CMakeBuildUtilities.cmake
index 78aa95a..15bc35b 100644
--- a/Source/Modules/CMakeBuildUtilities.cmake
+++ b/Source/Modules/CMakeBuildUtilities.cmake
@@ -181,6 +181,10 @@
endif()
set(CMAKE_EXPAT_INCLUDES ${EXPAT_INCLUDE_DIRS})
set(CMAKE_EXPAT_LIBRARIES ${EXPAT_LIBRARIES})
+ # Expat's CMake package provides a lower-case target name.
+ if(NOT TARGET EXPAT::EXPAT AND TARGET expat::expat)
+ add_library(EXPAT::EXPAT ALIAS expat::expat)
+ endif()
else()
set(CMAKE_EXPAT_INCLUDES)
set(CMAKE_EXPAT_LIBRARIES cmexpat)
@@ -290,7 +294,11 @@
set(ENABLE_WIN32_XMLLITE OFF)
set(ENABLE_XATTR OFF)
set(ENABLE_ACL OFF)
- set(ENABLE_ICONV OFF)
+ if(WIN32)
+ set(ENABLE_ICONV OFF)
+ else()
+ set(ENABLE_ICONV ON)
+ endif()
set(ENABLE_TEST OFF)
set(ENABLE_COVERAGE OFF)
set(ENABLE_INSTALL OFF)
diff --git a/Source/QtDialog/AddCacheEntry.cxx b/Source/QtDialog/AddCacheEntry.cxx
index 3c3be35..e354d24 100644
--- a/Source/QtDialog/AddCacheEntry.cxx
+++ b/Source/QtDialog/AddCacheEntry.cxx
@@ -2,10 +2,11 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "AddCacheEntry.h"
-#include "QCMakeSizeType.h"
#include <QCompleter>
#include <QMetaProperty>
+#include "QCMakeSizeType.h"
+
static int const NumTypes = 4;
static int const DefaultTypeIndex = 0;
static QByteArray const TypeStrings[NumTypes] = { "BOOL", "PATH", "FILEPATH",
diff --git a/Source/QtDialog/AddCacheEntry.h b/Source/QtDialog/AddCacheEntry.h
index c289c6b..d9563b9 100644
--- a/Source/QtDialog/AddCacheEntry.h
+++ b/Source/QtDialog/AddCacheEntry.h
@@ -2,11 +2,11 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
-#include "QCMake.h"
#include <QCheckBox>
#include <QStringList>
#include <QWidget>
+#include "QCMake.h"
#include "ui_AddCacheEntry.h"
class AddCacheEntry
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index e74b871..dfc8265 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include <iostream>
-#include "QCMake.h" // include to disable MS warnings
#include <QApplication>
#include <QDir>
#include <QLocale>
@@ -23,6 +22,8 @@
#include "cmSystemTools.h" // IWYU pragma: keep
#include "cmake.h"
+#include "QCMake.h" // include to disable MS warnings
+
namespace {
cmDocumentationEntry const cmDocumentationName = {
{},
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 34e9c9f..eb3a534 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -30,16 +30,15 @@
# include <QWinTaskbarProgress>
#endif
-#include "QCMake.h"
-#include "QCMakeCacheView.h"
-#include "QCMakeSizeType.h"
-
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "AddCacheEntry.h"
#include "EnvironmentDialog.h"
#include "FirstConfigure.h"
+#include "QCMake.h"
+#include "QCMakeCacheView.h"
+#include "QCMakeSizeType.h"
#include "RegexExplorer.h"
#include "WarningMessagesDialog.h"
@@ -191,9 +190,6 @@
a = OptionsMenu->addAction(tr("Warning Messages..."));
QObject::connect(a, &QAction::triggered, this,
&CMakeSetupDialog::doWarningMessagesDialog);
- this->WarnUninitializedAction =
- OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
- this->WarnUninitializedAction->setCheckable(true);
QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
debugAction->setCheckable(true);
@@ -342,13 +338,6 @@
QObject::connect(this->Environment, &QAbstractButton::clicked, this,
&CMakeSetupDialog::editEnvironment);
- QObject::connect(this->WarnUninitializedAction, &QAction::triggered,
- this->CMakeThread->cmakeInstance(),
- &QCMake::setWarnUninitializedMode);
- QObject::connect(this->CMakeThread->cmakeInstance(),
- &QCMake::warnUninitializedModeChanged,
- this->WarnUninitializedAction, &QAction::setChecked);
-
if (!this->SourceDirectory->text().isEmpty() &&
!this->DeferredPreset.isNull()) {
this->onSourceDirectoryChanged(this->SourceDirectory->text());
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index e5cd753..8e42ef9 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -4,13 +4,13 @@
#include <memory>
-#include "QCMake.h"
-#include "QCMakePreset.h"
#include <QEventLoop>
#include <QMainWindow>
#include <QThread>
#include <QVector>
+#include "QCMake.h"
+#include "QCMakePreset.h"
#include "ui_CMakeSetupDialog.h"
class QCMakePresetItemModel;
@@ -119,7 +119,6 @@
QAction* ExitAction;
QAction* ConfigureAction;
QAction* GenerateAction;
- QAction* WarnUninitializedAction;
QAction* InstallForCommandLineAction;
State CurrentState;
QString DeferredPreset;
diff --git a/Source/QtDialog/EnvironmentDialog.cxx b/Source/QtDialog/EnvironmentDialog.cxx
index 8ffb7f1..1a9db4e 100644
--- a/Source/QtDialog/EnvironmentDialog.cxx
+++ b/Source/QtDialog/EnvironmentDialog.cxx
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "EnvironmentDialog.h"
-#include "QCMakeWidgets.h"
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QItemSelectionModel>
@@ -11,6 +10,8 @@
#include <QMessageBox>
#include <QStandardItem>
+#include "QCMakeWidgets.h"
+
EnvironmentItemModel::EnvironmentItemModel(
QProcessEnvironment const& environment, QObject* parent)
: QStandardItemModel(parent)
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index 4a3133e..2886ed8 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -1,7 +1,6 @@
#include "FirstConfigure.h"
-#include "QCMakeSizeType.h"
#include <QComboBox>
#include <QRadioButton>
#include <QSettings>
@@ -10,6 +9,7 @@
#include "cmStringAlgorithms.h"
#include "Compilers.h"
+#include "QCMakeSizeType.h"
StartCompilerSetup::StartCompilerSetup(QString defaultGeneratorPlatform,
QString defaultGeneratorToolset,
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index cf031b1..9e11197 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -6,12 +6,12 @@
#include <cm/memory>
-#include "QCMakeSizeType.h"
#include <QCoreApplication>
#include <QDir>
#include <QString>
#include <QVector>
+#include "cmDiagnostics.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmMessageMetadata.h"
@@ -19,6 +19,8 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "QCMakeSizeType.h"
+
#ifdef Q_OS_WIN
# include "qt_windows.h" // For SetErrorMode
#endif
@@ -28,7 +30,6 @@
, StartEnvironment(QProcessEnvironment::systemEnvironment())
, Environment(QProcessEnvironment::systemEnvironment())
{
- this->WarnUninitializedMode = false;
qRegisterMetaType<QCMakeProperty>();
qRegisterMetaType<QCMakePropertyList>();
qRegisterMetaType<QProcessEnvironment>();
@@ -171,27 +172,8 @@
QString::fromStdString(expandedPreset->BinaryDir);
this->setBinaryDirectory(binaryDir);
}
- if (expandedPreset->WarnDev) {
- this->CMakeInstance->SetSuppressDevWarnings(
- !*expandedPreset->WarnDev);
- }
- if (expandedPreset->ErrorDev) {
- this->CMakeInstance->SetDevWarningsAsErrors(
- *expandedPreset->ErrorDev);
- }
- if (expandedPreset->WarnDeprecated) {
- this->CMakeInstance->SetSuppressDeprecatedWarnings(
- !*expandedPreset->WarnDeprecated);
- }
- if (expandedPreset->ErrorDeprecated) {
- this->CMakeInstance->SetDeprecatedWarningsAsErrors(
- *expandedPreset->ErrorDeprecated);
- }
- if (expandedPreset->WarnUninitialized) {
- this->WarnUninitializedMode = *expandedPreset->WarnUninitialized;
- emit this->warnUninitializedModeChanged(
- *expandedPreset->WarnUninitialized);
- }
+ this->CMakeInstance->SetDiagnosticsFromPreset(expandedPreset->Warnings,
+ expandedPreset->Errors);
this->Environment = this->StartEnvironment;
for (auto const& v : expandedPreset->Environment) {
if (v.second) {
@@ -258,7 +240,6 @@
this->CMakeInstance->SetGeneratorPlatform(this->Platform.toStdString());
this->CMakeInstance->SetGeneratorToolset(this->Toolset.toStdString());
this->CMakeInstance->LoadCache();
- this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
this->CMakeInstance->PreLoadCMakeFiles();
InterruptFlag = 0;
@@ -667,49 +648,17 @@
return this->CMakeInstance->GetDebugOutput();
}
-bool QCMake::getSuppressDevWarnings()
+void QCMake::setDiagnosticAction(cmDiagnostics::DiagnosticCategory category,
+ cmDiagnostics::DiagnosticAction action)
{
- return this->CMakeInstance->GetSuppressDevWarnings();
+ this->CMakeInstance->GetCurrentSnapshot().SetDiagnostic(category, action,
+ false);
}
-void QCMake::setSuppressDevWarnings(bool value)
+cmDiagnosticAction QCMake::getDiagnosticAction(
+ cmDiagnosticCategory category) const
{
- this->CMakeInstance->SetSuppressDevWarnings(value);
-}
-
-bool QCMake::getSuppressDeprecatedWarnings()
-{
- return this->CMakeInstance->GetSuppressDeprecatedWarnings();
-}
-
-void QCMake::setSuppressDeprecatedWarnings(bool value)
-{
- this->CMakeInstance->SetSuppressDeprecatedWarnings(value);
-}
-
-bool QCMake::getDevWarningsAsErrors()
-{
- return this->CMakeInstance->GetDevWarningsAsErrors();
-}
-
-void QCMake::setDevWarningsAsErrors(bool value)
-{
- this->CMakeInstance->SetDevWarningsAsErrors(value);
-}
-
-bool QCMake::getDeprecatedWarningsAsErrors()
-{
- return this->CMakeInstance->GetDeprecatedWarningsAsErrors();
-}
-
-void QCMake::setDeprecatedWarningsAsErrors(bool value)
-{
- this->CMakeInstance->SetDeprecatedWarningsAsErrors(value);
-}
-
-void QCMake::setWarnUninitializedMode(bool value)
-{
- this->WarnUninitializedMode = value;
+ return this->CMakeInstance->GetCurrentSnapshot().GetDiagnostic(category);
}
void QCMake::checkOpenPossible()
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index 50305f9..32c964c 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCMakePresetsGraph.h"
+#include "cmDiagnostics.h"
#include "cmake.h"
#ifdef _MSC_VER
@@ -15,7 +16,6 @@
#include <memory>
#include <vector>
-#include "QCMakePreset.h"
#include <QAtomicInt>
#include <QList>
#include <QMetaType>
@@ -26,6 +26,8 @@
#include <QTimer>
#include <QVariant>
+#include "QCMakePreset.h"
+
/// struct to represent cmake properties in Qt
/// Value is of type String or Bool
struct QCMakeProperty
@@ -104,24 +106,9 @@
void reloadCache();
/// set whether to do debug output
void setDebugOutput(bool);
- /// get whether to do suppress dev warnings
- bool getSuppressDevWarnings();
- /// set whether to do suppress dev warnings
- void setSuppressDevWarnings(bool value);
- /// get whether to do suppress deprecated warnings
- bool getSuppressDeprecatedWarnings();
- /// set whether to do suppress deprecated warnings
- void setSuppressDeprecatedWarnings(bool value);
- /// get whether to treat developer (author) warnings as errors
- bool getDevWarningsAsErrors();
- /// set whether to treat developer (author) warnings as errors
- void setDevWarningsAsErrors(bool value);
- /// get whether to treat deprecated warnings as errors
- bool getDeprecatedWarningsAsErrors();
- /// set whether to treat deprecated warnings as errors
- void setDeprecatedWarningsAsErrors(bool value);
- /// set whether to run cmake with warnings about uninitialized variables
- void setWarnUninitializedMode(bool value);
+ /// set diagnostic action
+ void setDiagnosticAction(cmDiagnostics::DiagnosticCategory,
+ cmDiagnostics::DiagnosticAction);
/// check if project IDE open is possible and emit openPossible signal
void checkOpenPossible();
/// Reload the preset files and tree
@@ -144,6 +131,8 @@
std::vector<cmake::GeneratorInfo> const& availableGenerators() const;
/// get whether to do debug output
bool getDebugOutput() const;
+ /// get diagnostic action
+ cmDiagnosticAction getDiagnosticAction(cmDiagnosticCategory) const;
signals:
/// signal when properties change (during read from disk or configure
@@ -162,8 +151,6 @@
void presetChanged(QString const& name);
/// signal when there's an error reading the presets files
void presetLoadError(QString const& dir, QString const& error);
- /// signal when uninitialized warning changes
- void warnUninitializedModeChanged(bool value);
/// signal for progress events
void progressChanged(QString const& msg, float percent);
/// signal when configure is done
@@ -195,7 +182,6 @@
void stderrCallback(std::string const& msg);
void setUpEnvironment() const;
- bool WarnUninitializedMode;
QString SourceDirectory;
QString BinaryDirectory;
QString MaybeRelativeBinaryDirectory;
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index fa2ad3d..e9eb792 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -2,8 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "QCMakeCacheView.h"
-#include "QCMakeSizeType.h"
-#include "QCMakeWidgets.h"
#include <QApplication>
#include <QEvent>
#include <QHBoxLayout>
@@ -13,6 +11,9 @@
#include <QSortFilterProxyModel>
#include <QStyle>
+#include "QCMakeSizeType.h"
+#include "QCMakeWidgets.h"
+
// filter for searches
class QCMakeSearchFilter : public QSortFilterProxyModel
{
diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h
index 8d2c742..a334673 100644
--- a/Source/QtDialog/QCMakeCacheView.h
+++ b/Source/QtDialog/QCMakeCacheView.h
@@ -2,13 +2,14 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
-#include "QCMake.h"
-#include "QCMakeSizeType.h"
#include <QItemDelegate>
#include <QSet>
#include <QStandardItemModel>
#include <QTreeView>
+#include "QCMake.h"
+#include "QCMakeSizeType.h"
+
class QSortFilterProxyModel;
class QCMakeCacheModel;
class QCMakeAdvancedFilter;
diff --git a/Source/QtDialog/QCMakePresetComboBox.h b/Source/QtDialog/QCMakePresetComboBox.h
index 47d8b8e..e7ac173 100644
--- a/Source/QtDialog/QCMakePresetComboBox.h
+++ b/Source/QtDialog/QCMakePresetComboBox.h
@@ -2,12 +2,13 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
-#include "QCMakePreset.h"
#include <QComboBox>
#include <QObject>
#include <QString>
#include <QVector>
+#include "QCMakePreset.h"
+
class QCMakePresetItemModel;
class QCMakePresetComboBox : public QComboBox
diff --git a/Source/QtDialog/QCMakePresetItemModel.cxx b/Source/QtDialog/QCMakePresetItemModel.cxx
index cb4e4fe..cae0a42 100644
--- a/Source/QtDialog/QCMakePresetItemModel.cxx
+++ b/Source/QtDialog/QCMakePresetItemModel.cxx
@@ -2,9 +2,10 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "QCMakePresetItemModel.h"
-#include "QCMakeSizeType.h"
#include <QFont>
+#include "QCMakeSizeType.h"
+
QCMakePresetItemModel::QCMakePresetItemModel(QObject* parent)
: QAbstractItemModel(parent)
{
diff --git a/Source/QtDialog/QCMakePresetItemModel.h b/Source/QtDialog/QCMakePresetItemModel.h
index b565cbd..a3a0cf3 100644
--- a/Source/QtDialog/QCMakePresetItemModel.h
+++ b/Source/QtDialog/QCMakePresetItemModel.h
@@ -4,7 +4,6 @@
#include <cm/optional>
-#include "QCMakePreset.h"
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QString>
@@ -12,6 +11,8 @@
#include <QVector>
#include <QtGlobal>
+#include "QCMakePreset.h"
+
class QObject;
class QCMakePresetItemModel : public QAbstractItemModel
diff --git a/Source/QtDialog/WarningMessagesDialog.cxx b/Source/QtDialog/WarningMessagesDialog.cxx
index 3728693..cf4c8e5 100644
--- a/Source/QtDialog/WarningMessagesDialog.cxx
+++ b/Source/QtDialog/WarningMessagesDialog.cxx
@@ -2,6 +2,20 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "WarningMessagesDialog.h"
+#include "cm/string_view"
+
+#include <QButtonGroup>
+#include <QHeaderView>
+#include <QRadioButton>
+#include <QToolButton>
+#include <QTreeWidget>
+#include <QTreeWidgetItem>
+
+#include "cmDiagnostics.h"
+
+#include "QCMake.h"
+#include "QCMakeSizeType.h"
+
WarningMessagesDialog::WarningMessagesDialog(QWidget* prnt, QCMake* instance)
: QDialog(prnt)
, cmakeInstance(instance)
@@ -13,84 +27,83 @@
void WarningMessagesDialog::setInitialValues()
{
- this->suppressDeveloperWarnings->setChecked(
- this->cmakeInstance->getSuppressDevWarnings());
- this->suppressDeprecatedWarnings->setChecked(
- this->cmakeInstance->getSuppressDeprecatedWarnings());
+ QHeaderView* const header = this->treeWidget->header();
+ header->setSectionResizeMode(0, QHeaderView::Stretch);
+ header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+ header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
+ header->setSectionResizeMode(3, QHeaderView::ResizeToContents);
- this->developerWarningsAsErrors->setChecked(
- this->cmakeInstance->getDevWarningsAsErrors());
- this->deprecatedWarningsAsErrors->setChecked(
- this->cmakeInstance->getDeprecatedWarningsAsErrors());
+ std::map<unsigned, QTreeWidgetItem*> items = {
+ { 0, this->treeWidget->invisibleRootItem() },
+ };
+
+ for (unsigned i = 1; i < cmDiagnostics::CategoryCount; ++i) {
+ auto const category = static_cast<cmDiagnosticCategory>(i);
+ cm::string_view const cname =
+ cmDiagnostics::GetCategoryString(category).substr(4);
+ QTreeWidgetItem* const parent =
+ items[cmDiagnostics::CategoryInfo[category].Parent];
+
+ QTreeWidgetItem* const item = new QTreeWidgetItem(parent);
+ item->setText(0,
+ QString::fromUtf8(cname.data(),
+ static_cast<cm_qsizetype>(cname.size())));
+
+ auto makeButton = [](QString const& text) {
+ QToolButton* const button = new QToolButton;
+ button->setCheckable(true);
+ button->setText(text);
+ return button;
+ };
+ QAbstractButton* const ignore = makeButton(tr("Ignore"));
+ QAbstractButton* const warn = makeButton(tr("Warn"));
+ QAbstractButton* const error = makeButton(tr("Error"));
+
+ QButtonGroup* const buttonGroup = new QButtonGroup(treeWidget);
+ buttonGroup->addButton(ignore, cmDiagnosticAction::Ignore);
+ buttonGroup->addButton(warn, cmDiagnosticAction::Warn);
+ buttonGroup->addButton(error, cmDiagnosticAction::SendError);
+ buttonGroup->setExclusive(true);
+ this->buttons.emplace(i, buttonGroup);
+
+ treeWidget->setItemWidget(item, 1, ignore);
+ treeWidget->setItemWidget(item, 2, warn);
+ treeWidget->setItemWidget(item, 3, error);
+
+ cmDiagnosticAction const action =
+ this->cmakeInstance->getDiagnosticAction(category);
+ switch (action) {
+ case cmDiagnostics::SendError:
+ case cmDiagnostics::FatalError:
+ error->setChecked(true);
+ break;
+ case cmDiagnostics::Warn:
+ warn->setChecked(true);
+ break;
+ default:
+ ignore->setChecked(true);
+ break;
+ }
+
+ items.emplace(i, item);
+ }
+
+ for (auto const& ii : items) {
+ ii.second->setExpanded(true);
+ }
}
void WarningMessagesDialog::setupSignals()
{
-#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
- static auto const checkStateChanged = &QCheckBox::checkStateChanged;
-#else
- static auto const checkStateChanged = &QCheckBox::stateChanged;
-#endif
QObject::connect(this->buttonBox, &QDialogButtonBox::accepted, this,
&WarningMessagesDialog::doAccept);
- QObject::connect(this->suppressDeveloperWarnings, checkStateChanged, this,
- &WarningMessagesDialog::doSuppressDeveloperWarningsChanged);
- QObject::connect(
- this->suppressDeprecatedWarnings, checkStateChanged, this,
- &WarningMessagesDialog::doSuppressDeprecatedWarningsChanged);
-
- QObject::connect(this->developerWarningsAsErrors, checkStateChanged, this,
- &WarningMessagesDialog::doDeveloperWarningsAsErrorsChanged);
- QObject::connect(
- this->deprecatedWarningsAsErrors, checkStateChanged, this,
- &WarningMessagesDialog::doDeprecatedWarningsAsErrorsChanged);
}
void WarningMessagesDialog::doAccept()
{
- this->cmakeInstance->setSuppressDevWarnings(
- this->suppressDeveloperWarnings->isChecked());
- this->cmakeInstance->setSuppressDeprecatedWarnings(
- this->suppressDeprecatedWarnings->isChecked());
-
- this->cmakeInstance->setDevWarningsAsErrors(
- this->developerWarningsAsErrors->isChecked());
- this->cmakeInstance->setDeprecatedWarningsAsErrors(
- this->deprecatedWarningsAsErrors->isChecked());
-}
-
-void WarningMessagesDialog::doSuppressDeveloperWarningsChanged(
- CheckState state)
-{
- // no warnings implies no errors either
- if (state) {
- this->developerWarningsAsErrors->setChecked(false);
- }
-}
-
-void WarningMessagesDialog::doSuppressDeprecatedWarningsChanged(
- CheckState state)
-{
- // no warnings implies no errors either
- if (state) {
- this->deprecatedWarningsAsErrors->setChecked(false);
- }
-}
-
-void WarningMessagesDialog::doDeveloperWarningsAsErrorsChanged(
- CheckState state)
-{
- // warnings as errors implies warnings are not suppressed
- if (state) {
- this->suppressDeveloperWarnings->setChecked(false);
- }
-}
-
-void WarningMessagesDialog::doDeprecatedWarningsAsErrorsChanged(
- CheckState state)
-{
- // warnings as errors implies warnings are not suppressed
- if (state) {
- this->suppressDeprecatedWarnings->setChecked(false);
+ for (auto const& ii : this->buttons) {
+ this->cmakeInstance->setDiagnosticAction(
+ static_cast<cmDiagnosticCategory>(ii.first),
+ static_cast<cmDiagnosticAction>(ii.second->checkedId()));
}
}
diff --git a/Source/QtDialog/WarningMessagesDialog.h b/Source/QtDialog/WarningMessagesDialog.h
index e5f0660..cf32841 100644
--- a/Source/QtDialog/WarningMessagesDialog.h
+++ b/Source/QtDialog/WarningMessagesDialog.h
@@ -2,12 +2,17 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
-#include "QCMake.h"
+#include <map>
+
#include <QDialog>
#include <QWidget>
#include "ui_WarningMessagesDialog.h"
+class QButtonGroup;
+
+class QCMake;
+
/**
* Dialog window for setting the warning message related options.
*/
@@ -17,12 +22,6 @@
{
Q_OBJECT
-#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
- using CheckState = Qt::CheckState;
-#else
- using CheckState = int;
-#endif
-
public:
WarningMessagesDialog(QWidget* prnt, QCMake* instance);
@@ -32,30 +31,9 @@
*/
void doAccept();
- /**
- * Handler for checked state changed event of the suppress developer warnings
- * checkbox.
- */
- void doSuppressDeveloperWarningsChanged(CheckState state);
- /**
- * Handler for checked state changed event of the suppress deprecated
- * warnings checkbox.
- */
- void doSuppressDeprecatedWarningsChanged(CheckState state);
-
- /**
- * Handler for checked state changed event of the developer warnings as
- * errors checkbox.
- */
- void doDeveloperWarningsAsErrorsChanged(CheckState state);
- /**
- * Handler for checked state changed event of the deprecated warnings as
- * errors checkbox.
- */
- void doDeprecatedWarningsAsErrorsChanged(CheckState state);
-
private:
QCMake* cmakeInstance;
+ std::map<unsigned, QButtonGroup*> buttons;
/**
* Set the initial values of the widgets on this dialog window, using the
diff --git a/Source/QtDialog/WarningMessagesDialog.ui b/Source/QtDialog/WarningMessagesDialog.ui
index 3b35cbc..72c4939 100644
--- a/Source/QtDialog/WarningMessagesDialog.ui
+++ b/Source/QtDialog/WarningMessagesDialog.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>300</width>
+ <width>450</width>
<height>300</height>
</rect>
</property>
@@ -18,103 +18,54 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="groupBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <widget class="QTreeWidget" name="treeWidget">
+ <property name="showDropIndicator" stdset="0">
+ <bool>false</bool>
</property>
- <property name="title">
- <string>Suppress Warnings</string>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QCheckBox" name="suppressDeveloperWarnings">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="toolTip">
- <string>Suppress developer (author) warnings.</string>
- </property>
- <property name="text">
- <string>Developer Warnings</string>
- </property>
- <property name="tristate">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="suppressDeprecatedWarnings">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="toolTip">
- <string>Suppress deprecated warnings.</string>
- </property>
- <property name="text">
- <string>Deprecated Warnings</string>
- </property>
- <property name="tristate">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
</property>
- <property name="title">
- <string>Warnings as Errors</string>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QCheckBox" name="developerWarningsAsErrors">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="toolTip">
- <string>Treat developer (author) warnings as errors.</string>
- </property>
- <property name="text">
- <string>Developer Warnings as Errors</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="deprecatedWarningsAsErrors">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="toolTip">
- <string>Treat deprecated warnings as errors.</string>
- </property>
- <property name="text">
- <string>Deprecated Warnings as Errors</string>
- </property>
- </widget>
- </item>
- </layout>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="expandsOnDoubleClick">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="headerStretchLastSection">
+ <bool>false</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string notr="true">Category</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true">Ignore</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true">Warn</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true">Error</string>
+ </property>
+ </column>
</widget>
</item>
<item>
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 0adcefd..374e476 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -3,7 +3,6 @@
#include "cmArchiveWrite.h"
#include <cstdlib>
-#include <cstring>
#include <ctime>
#include <iostream>
#include <limits>
@@ -12,6 +11,7 @@
#include <thread>
#include <cm/algorithm>
+#include <cm/string_view>
#include <cm3p/archive.h>
#include <cm3p/archive_entry.h>
@@ -43,6 +43,10 @@
{
#ifdef _WIN32
// libarchive converts our UTF-8 encoding to the archive's encoding.
+ // `archive_entry_update_pathname_utf8` always populates the WCS form too.
+ // It also populates the MBS form if possible, but we ignore conversion
+ // failure because the archive formats support converting directly from
+ // the WCS form to the archive's encoding without using the MBS form.
archive_entry_update_pathname_utf8(e, dest);
#else
// libarchive converts our locale's encoding to the archive's encoding.
@@ -92,8 +96,9 @@
};
cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
- std::string const& format, int compressionLevel,
- int numThreads)
+ std::string const& format,
+ std::string const& encoding,
+ int compressionLevel, int numThreads)
: Stream(os)
, Archive(archive_write_new())
, Disk(archive_read_disk_new())
@@ -222,6 +227,20 @@
}
}
+ // 7zip always uses UTF16-LE for the headers and doesn't support
+ // header encoding specification.
+ // arbsd can use the default encoding of the system only.
+ if (!is7zip && format != "arbsd" && encoding != "OEM") {
+ char const* formatForOptions = format == "paxr" ? "pax" : format.c_str();
+ if (archive_write_set_format_option(this->Archive, formatForOptions,
+ "hdrcharset",
+ encoding.c_str()) != ARCHIVE_OK) {
+ this->Error = cmStrCat("archive_write_set_format_option(hdrcharset): ",
+ cm_archive_error_string(this->Archive));
+ return;
+ }
+ }
+
if (isFormatSupportsCompressionNatively || compressionLevel != 0) {
std::string compressionLevelStr = std::to_string(compressionLevel);
std::string archiveFilterName;
@@ -399,15 +418,14 @@
if (!path.empty() && path.back() == '/') {
path.erase(path.size() - 1);
}
- this->AddPath(path.c_str(), skip, prefix, recursive);
+ this->AddPath(path, skip, prefix, recursive);
return this->Okay();
}
-bool cmArchiveWrite::AddPath(char const* path, size_t skip, char const* prefix,
- bool recursive)
+bool cmArchiveWrite::AddPath(std::string const& path, size_t skip,
+ char const* prefix, bool recursive)
{
- if (strcmp(path, ".") != 0 ||
- (this->Format != "zip" && this->Format != "7zip")) {
+ if (path != "." || (this->Format != "zip" && this->Format != "7zip")) {
if (!this->AddFile(path, skip, prefix)) {
return false;
}
@@ -425,11 +443,11 @@
std::string::size_type end = next.size();
unsigned long n = d.GetNumberOfFiles();
for (unsigned long i = 0; i < n; ++i) {
- char const* file = d.GetFile(i);
- if (strcmp(file, ".") != 0 && strcmp(file, "..") != 0) {
+ std::string const& file = d.GetFileName(i);
+ if (file != "." && file != "..") {
next.erase(end);
next += file;
- if (!this->AddPath(next.c_str(), skip, prefix)) {
+ if (!this->AddPath(next, skip, prefix)) {
return false;
}
}
@@ -438,15 +456,16 @@
return true;
}
-bool cmArchiveWrite::AddFile(char const* file, size_t skip, char const* prefix)
+bool cmArchiveWrite::AddFile(std::string const& file, size_t skip,
+ char const* prefix)
{
this->Error = "";
// Skip the file if we have no name for it. This may happen on a
// top-level directory, which does not need to be included anyway.
- if (skip >= strlen(file)) {
+ if (skip >= file.length()) {
return true;
}
- char const* out = file + skip;
+ cm::string_view out = cm::string_view(file).substr(skip);
// Meta-data.
std::string dest = cmStrCat(prefix ? prefix : "", out);
@@ -538,9 +557,9 @@
return true;
}
-bool cmArchiveWrite::AddData(char const* file, size_t size)
+bool cmArchiveWrite::AddData(std::string const& file, size_t size)
{
- cmsys::ifstream fin(file, std::ios::in | std::ios::binary);
+ cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary);
if (!fin) {
this->Error = cmStrCat("Error opening \"", file,
"\": ", cmSystemTools::GetLastSystemError());
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index dac0a57..dfefc72 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -55,8 +55,9 @@
/** Construct with output stream to which to write archive. */
cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
- std::string const& format = "paxr", int compressionLevel = 0,
- int numThreads = 1);
+ std::string const& format = "paxr",
+ std::string const& encoding = "UTF-8",
+ int compressionLevel = 0, int numThreads = 1);
~cmArchiveWrite();
@@ -144,10 +145,10 @@
private:
bool Okay() const { return this->Error.empty(); }
- bool AddPath(char const* path, size_t skip, char const* prefix,
+ bool AddPath(std::string const& path, size_t skip, char const* prefix,
bool recursive = true);
- bool AddFile(char const* file, size_t skip, char const* prefix);
- bool AddData(char const* file, size_t size);
+ bool AddFile(std::string const& file, size_t skip, char const* prefix);
+ bool AddData(std::string const& file, size_t size);
struct Callback;
friend struct Callback;
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index d571a1a..947dc7c 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -46,7 +46,7 @@
if (dir.Load(tdir)) {
size_t numfiles = dir.GetNumberOfFiles();
for (size_t i = 0; i < numfiles; ++i) {
- std::string file = dir.GetFile(static_cast<unsigned long>(i));
+ std::string const& file = dir.GetFileName(i);
// Split the filename into base and extension
std::string::size_type dotpos = file.rfind('.');
if (dotpos != std::string::npos) {
diff --git a/Source/cmBlockCommand.cxx b/Source/cmBlockCommand.cxx
index de31848..575efe6 100644
--- a/Source/cmBlockCommand.cxx
+++ b/Source/cmBlockCommand.cxx
@@ -25,7 +25,8 @@
enum class ScopeType : std::uint8_t
{
VARIABLES,
- POLICIES
+ POLICIES,
+ DIAGNOSTICS,
};
using ScopeSet = cm::enum_set<ScopeType>;
@@ -41,6 +42,7 @@
private:
std::unique_ptr<cmMakefile::PolicyPushPop> PolicyScope;
std::unique_ptr<cmMakefile::VariablePushPop> VariableScope;
+ std::unique_ptr<cmMakefile::DiagnosticPushPop> DiagnosticScope;
};
BlockScopePushPop::BlockScopePushPop(cmMakefile* mf, ScopeSet const& scopes)
@@ -51,6 +53,9 @@
if (scopes.contains(ScopeType::VARIABLES)) {
this->VariableScope = cm::make_unique<cmMakefile::VariablePushPop>(mf);
}
+ if (scopes.contains(ScopeType::DIAGNOSTICS)) {
+ this->DiagnosticScope = cm::make_unique<cmMakefile::DiagnosticPushPop>(mf);
+ }
}
class cmBlockFunctionBlocker : public cmFunctionBlocker
@@ -177,12 +182,17 @@
scopes.insert(ScopeType::POLICIES);
continue;
}
+ if (scope == "DIAGNOSTICS"_s) {
+ scopes.insert(ScopeType::DIAGNOSTICS);
+ continue;
+ }
status.SetError(cmStrCat("SCOPE_FOR unsupported scope \"", scope, '"'));
cmSystemTools::SetFatalErrorOccurred();
return false;
}
} else {
- scopes = { ScopeType::VARIABLES, ScopeType::POLICIES };
+ scopes = { ScopeType::VARIABLES, ScopeType::POLICIES,
+ ScopeType::DIAGNOSTICS };
}
if (!scopes.contains(ScopeType::VARIABLES) &&
!parsedArgs.Propagate.empty()) {
diff --git a/Source/cmBuildDatabase.cxx b/Source/cmBuildDatabase.cxx
index b25ca27..f5ddafa 100644
--- a/Source/cmBuildDatabase.cxx
+++ b/Source/cmBuildDatabase.cxx
@@ -17,8 +17,9 @@
#include "cmsys/FStream.hxx"
#include "cmComputeLinkInformation.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
@@ -449,9 +450,9 @@
bool isPrivate = true;
if (sf->GetLanguage() == "CXX"_s) {
auto const* fs = gt->GetFileSetForSource(config, sf);
- if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
isCXXModule = true;
- isPrivate = !cmFileSetVisibilityIsForInterface(fs->GetVisibility());
+ isPrivate = !fs->IsForInterface();
}
}
diff --git a/Source/cmCMakeDiagnosticCommand.cxx b/Source/cmCMakeDiagnosticCommand.cxx
new file mode 100644
index 0000000..d05a489
--- /dev/null
+++ b/Source/cmCMakeDiagnosticCommand.cxx
@@ -0,0 +1,129 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmCMakeDiagnosticCommand.h"
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include "cmDiagnostics.h"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+
+namespace {
+using AlterFunction = bool (cmMakefile::*)(cmDiagnosticCategory,
+ cmDiagnosticAction, bool);
+
+bool HandleAlterMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status, AlterFunction function,
+ bool recursive)
+{
+ if (args.size() < 3 || args.size() > 4) {
+ status.SetError(cmStrCat(
+ args[0], " must be given exactly 2 or 3 additional arguments."_s));
+ return false;
+ }
+
+ if (args.size() == 4) {
+ if (args[3] == "RECURSE") {
+ recursive = true;
+ } else if (args[3] == "NO_RECURSE") {
+ recursive = false;
+ } else {
+ status.SetError(
+ cmStrCat(args[0], " given unknown option \""_s, args[3], "\"."_s));
+ return false;
+ }
+ }
+
+ cm::optional<cmDiagnosticAction> const action =
+ cmDiagnostics::GetDiagnosticAction(args[2]);
+ if (!action) {
+ status.SetError(cmStrCat(
+ args[0], " given unrecognized diagnostic action \"", args[2], "\"."_s));
+ return false;
+ }
+
+ cm::optional<cmDiagnosticCategory> const category =
+ cmDiagnostics::GetDiagnosticCategory(args[1]);
+ if (!category) {
+ status.SetError(cmStrCat(args[0],
+ " given unrecognized diagnostic category \"",
+ args[1], "\"."_s));
+ return false;
+ }
+
+ if (!(status.GetMakefile().*function)(*category, *action, recursive)) {
+ status.SetError(cmStrCat(args[0], " failed to set diagnostic action."_s));
+ return false;
+ }
+ return true;
+}
+
+bool HandleGetMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() != 3) {
+ status.SetError("GET must be given exactly 2 additional arguments.");
+ return false;
+ }
+
+ cm::optional<cmDiagnosticCategory> const category =
+ cmDiagnostics::GetDiagnosticCategory(args[1]);
+ if (!category) {
+ status.SetError(cmStrCat(args[0],
+ " given unrecognized diagnostic category \"",
+ args[1], "\"."_s));
+ return false;
+ }
+
+ cmDiagnosticAction const action =
+ status.GetMakefile().GetDiagnosticAction(*category);
+
+ status.GetMakefile().AddDefinition(args[2],
+ cmDiagnostics::GetActionString(action));
+ return true;
+}
+}
+
+// cmCMakeDiagnosticCommand
+bool cmCMakeDiagnosticCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("requires at least one argument.");
+ return false;
+ }
+
+ if (args[0] == "SET") {
+ return HandleAlterMode(args, status, &cmMakefile::SetDiagnostic, false);
+ }
+ if (args[0] == "PROMOTE") {
+ return HandleAlterMode(args, status, &cmMakefile::PromoteDiagnostic, true);
+ }
+ if (args[0] == "DEMOTE") {
+ return HandleAlterMode(args, status, &cmMakefile::DemoteDiagnostic, true);
+ }
+ if (args[0] == "GET") {
+ return HandleGetMode(args, status);
+ }
+ if (args[0] == "PUSH") {
+ if (args.size() > 1) {
+ status.SetError("PUSH may not be given additional arguments.");
+ return false;
+ }
+ status.GetMakefile().PushDiagnostic();
+ return true;
+ }
+ if (args[0] == "POP") {
+ if (args.size() > 1) {
+ status.SetError("POP may not be given additional arguments.");
+ return false;
+ }
+ status.GetMakefile().PopDiagnostic();
+ return true;
+ }
+
+ status.SetError(cmStrCat("given unknown first argument \"", args[0], '"'));
+ return false;
+}
diff --git a/Source/cmCMakeDiagnosticCommand.h b/Source/cmCMakeDiagnosticCommand.h
new file mode 100644
index 0000000..c5d6e8a
--- /dev/null
+++ b/Source/cmCMakeDiagnosticCommand.h
@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+/**
+ * \brief Set how CMake should handle diagnostics
+ *
+ * cmCMakeDiagnosticCommand sets how CMake should deal with diagnostics.
+ */
+bool cmCMakeDiagnosticCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
diff --git a/Source/cmCMakePresetsErrors.cxx b/Source/cmCMakePresetsErrors.cxx
index f2cbe84..6b454ac 100644
--- a/Source/cmCMakePresetsErrors.cxx
+++ b/Source/cmCMakePresetsErrors.cxx
@@ -189,6 +189,12 @@
"processor-count-based jobs preset support");
}
+void PASSTHROUGH_ARGS_UNSUPPORTED(cmJSONState* state)
+{
+ state->AddError("File version must be 12 or higher for "
+ "testPassthroughArguments preset support");
+}
+
void CYCLIC_INCLUDE(std::string const& file, cmJSONState* state)
{
state->AddError(cmStrCat("Cyclic include among preset files: ", file));
@@ -329,4 +335,18 @@
{
state->AddError("File version must be 8 or higher for $schema support");
}
+
+void DIAGNOSTIC_UNSUPPORTED(cm::string_view name, cm::string_view context,
+ int version, cmJSONState* state)
+{
+ state->AddError(cmStrCat("File version must be ", std::to_string(version),
+ " or higher for ", context, '.', name, " support"));
+}
+
+void DIAGNOSTIC_REMOVED(cm::string_view name, cm::string_view context,
+ int version, cmJSONState* state)
+{
+ state->AddError(cmStrCat("File version must be ", std::to_string(version),
+ " or lower for ", context, '.', name, " support"));
+}
}
diff --git a/Source/cmCMakePresetsErrors.h b/Source/cmCMakePresetsErrors.h
index 372ceb8..a153d92 100644
--- a/Source/cmCMakePresetsErrors.h
+++ b/Source/cmCMakePresetsErrors.h
@@ -6,6 +6,8 @@
#include <string>
+#include <cm/string_view>
+
#include <cm3p/json/value.h>
#include "cmJSONHelpers.h"
@@ -74,6 +76,8 @@
void JOBS_PROC_UNSUPPORTED(cmJSONState* state);
+void PASSTHROUGH_ARGS_UNSUPPORTED(cmJSONState* state);
+
void CYCLIC_INCLUDE(std::string const& file, cmJSONState* state);
void TEST_OUTPUT_TRUNCATION_UNSUPPORTED(cmJSONState* state);
@@ -121,4 +125,10 @@
std::string const& missingField, cmJSONState* state);
void SCHEMA_UNSUPPORTED(cmJSONState* state);
+
+void DIAGNOSTIC_UNSUPPORTED(cm::string_view name, cm::string_view context,
+ int version, cmJSONState* state);
+
+void DIAGNOSTIC_REMOVED(cm::string_view name, cm::string_view context,
+ int version, cmJSONState* state);
}
diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx
index 870315f..a6bde57 100644
--- a/Source/cmCMakePresetsGraph.cxx
+++ b/Source/cmCMakePresetsGraph.cxx
@@ -4,8 +4,8 @@
#include <algorithm>
#include <cassert>
-#include <cstddef>
#include <functional>
+#include <iomanip>
#include <iostream>
#include <iterator>
#include <utility>
@@ -27,6 +27,8 @@
case ExpandMacroResult::Ignore: \
out.reset(); \
return true; \
+ case ExpandMacroResult::Defer: \
+ CM_FALLTHROUGH; \
case ExpandMacroResult::Ok: \
break; \
} \
@@ -54,8 +56,13 @@
template <typename T>
using PresetMacroExpander =
cmCMakePresetsGraphInternal::PresetMacroExpander<T>;
+template <typename T>
+using ImmediateMacroExpander =
+ cmCMakePresetsGraphInternal::ImmediateMacroExpander<T>;
using cmCMakePresetsGraphInternal::ExpandMacros;
+bool gSkipNewLine = true;
+
void InheritString(std::string& child, std::string const& parent)
{
if (child.empty()) {
@@ -80,13 +87,21 @@
}
}
+template <typename K, typename V>
+void InheritMap(std::map<K, V>& child, std::map<K, V> const& parent)
+{
+ for (auto const& item : parent) {
+ child.insert(item);
+ }
+}
+
/**
* Check preset inheritance for cycles (using a DAG check algorithm) while
* also bubbling up fields through the inheritance hierarchy, then verify
* that each preset has the required fields, either directly or through
* inheritance.
*/
-template <class T>
+template <typename T>
bool VisitPreset(
T& preset,
std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
@@ -142,9 +157,7 @@
return false;
}
- for (auto const& v : parentPreset.Environment) {
- preset.Environment.insert(v);
- }
+ InheritMap(preset.Environment, parentPreset.Environment);
if (!preset.ConditionEvaluator) {
preset.ConditionEvaluator = parentPreset.ConditionEvaluator;
@@ -166,7 +179,7 @@
return true;
}
-template <class T>
+template <typename T>
bool ComputePresetInheritance(
std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
cmCMakePresetsGraph& graph)
@@ -210,7 +223,7 @@
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
MacroExpanderVector const& macroExpanders,
int version);
-template <class T>
+template <typename T>
class EnvironmentMacroExpander : public MacroExpander
{
std::map<std::string, CycleStatus>& EnvCycles;
@@ -259,156 +272,165 @@
}
};
-bool ExpandMacros(cmCMakePresetsGraph const& graph,
- ConfigurePreset const& preset,
- cm::optional<ConfigurePreset>& out,
- MacroExpanderVector const& macroExpanders)
+bool CheckExpandMacros(ConfigurePreset const& preset,
+ cm::optional<ConfigurePreset>& out,
+ MacroExpanderVector const& macroExpanders,
+ cmCMakePresetsGraph const* graph = nullptr)
{
+ int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;
+
std::string binaryDir = preset.BinaryDir;
- CHECK_EXPAND(out, binaryDir, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, binaryDir, macroExpanders, version);
if (!binaryDir.empty()) {
- if (!cmSystemTools::FileIsFullPath(binaryDir)) {
- binaryDir = cmStrCat(graph.SourceDir, '/', binaryDir);
+ if (graph) {
+ if (!cmSystemTools::FileIsFullPath(binaryDir)) {
+ binaryDir = cmStrCat(graph->SourceDir, '/', binaryDir);
+ }
+ out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
+ cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
+ } else {
+ // Defer path normalization until the graph is merged, but store the
+ // intermediate result.
+ out->BinaryDir = binaryDir;
}
- out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
- cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
}
if (!preset.InstallDir.empty()) {
std::string installDir = preset.InstallDir;
- CHECK_EXPAND(out, installDir, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, installDir, macroExpanders, version);
- if (!cmSystemTools::FileIsFullPath(installDir)) {
- installDir = cmStrCat(graph.SourceDir, '/', installDir);
+ if (graph) {
+ if (!cmSystemTools::FileIsFullPath(installDir)) {
+ installDir = cmStrCat(graph->SourceDir, '/', installDir);
+ }
+ out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
+ cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
+ } else {
+ // Defer path normalization until the graph is merged, but store the
+ // intermediate result.
+ out->InstallDir = installDir;
}
- out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
- cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
}
if (!preset.ToolchainFile.empty()) {
std::string toolchain = preset.ToolchainFile;
- CHECK_EXPAND(out, toolchain, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, toolchain, macroExpanders, version);
out->ToolchainFile = toolchain;
}
if (!preset.GraphVizFile.empty()) {
std::string graphVizFile = preset.GraphVizFile;
- CHECK_EXPAND(out, graphVizFile, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, graphVizFile, macroExpanders, version);
out->GraphVizFile = graphVizFile;
}
for (auto& variable : out->CacheVariables) {
if (variable.second) {
- CHECK_EXPAND(out, variable.second->Value, macroExpanders,
- graph.GetVersion(preset));
+ CHECK_EXPAND(out, variable.second->Value, macroExpanders, version);
}
}
return true;
}
-bool ExpandMacros(cmCMakePresetsGraph const& graph, BuildPreset const& preset,
- cm::optional<BuildPreset>& out,
- MacroExpanderVector const& macroExpanders)
+bool CheckExpandMacros(BuildPreset const& preset,
+ cm::optional<BuildPreset>& out,
+ MacroExpanderVector const& macroExpanders,
+ cmCMakePresetsGraph const* graph = nullptr)
{
+ int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;
+
for (auto& target : out->Targets) {
- CHECK_EXPAND(out, target, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, target, macroExpanders, version);
}
for (auto& nativeToolOption : out->NativeToolOptions) {
- CHECK_EXPAND(out, nativeToolOption, macroExpanders,
- graph.GetVersion(preset));
+ CHECK_EXPAND(out, nativeToolOption, macroExpanders, version);
}
return true;
}
-bool ExpandMacros(cmCMakePresetsGraph const& graph, TestPreset const& preset,
- cm::optional<TestPreset>& out,
- MacroExpanderVector const& macroExpanders)
+bool CheckExpandMacros(TestPreset const& preset, cm::optional<TestPreset>& out,
+ MacroExpanderVector const& macroExpanders,
+ cmCMakePresetsGraph const* graph = nullptr)
{
+ int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;
+
for (auto& overwrite : out->OverwriteConfigurationFile) {
- CHECK_EXPAND(out, overwrite, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, overwrite, macroExpanders, version);
}
if (out->Output) {
- CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders,
- graph.GetVersion(preset));
- CHECK_EXPAND(out, out->Output->OutputJUnitFile, macroExpanders,
- graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders, version);
+ CHECK_EXPAND(out, out->Output->OutputJUnitFile, macroExpanders, version);
}
if (out->Filter) {
if (out->Filter->Include) {
- CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders,
- graph.GetVersion(preset));
- CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders,
- graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders, version);
+ CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders, version);
if (out->Filter->Include->Index) {
CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
- macroExpanders, graph.GetVersion(preset));
+ macroExpanders, version);
}
}
if (out->Filter->Exclude) {
- CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders,
- graph.GetVersion(preset));
- CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders,
- graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders, version);
+ CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders, version);
if (out->Filter->Exclude->Fixtures) {
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders,
- graph.GetVersion(preset));
+ version);
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
- macroExpanders, graph.GetVersion(preset));
+ macroExpanders, version);
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
- macroExpanders, graph.GetVersion(preset));
+ macroExpanders, version);
}
}
}
if (out->Execution) {
CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders,
- graph.GetVersion(preset));
+ version);
}
return true;
}
-bool ExpandMacros(cmCMakePresetsGraph const& graph,
- PackagePreset const& preset,
- cm::optional<PackagePreset>& out,
- MacroExpanderVector const& macroExpanders)
+bool CheckExpandMacros(PackagePreset const& preset,
+ cm::optional<PackagePreset>& out,
+ MacroExpanderVector const& macroExpanders,
+ cmCMakePresetsGraph const* graph = nullptr)
{
+ int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;
+
for (auto& variable : out->Variables) {
- CHECK_EXPAND(out, variable.second, macroExpanders,
- graph.GetVersion(preset));
+ CHECK_EXPAND(out, variable.second, macroExpanders, version);
}
- CHECK_EXPAND(out, out->ConfigFile, macroExpanders, graph.GetVersion(preset));
- CHECK_EXPAND(out, out->PackageName, macroExpanders,
- graph.GetVersion(preset));
- CHECK_EXPAND(out, out->PackageVersion, macroExpanders,
- graph.GetVersion(preset));
- CHECK_EXPAND(out, out->PackageDirectory, macroExpanders,
- graph.GetVersion(preset));
- CHECK_EXPAND(out, out->VendorName, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->ConfigFile, macroExpanders, version);
+ CHECK_EXPAND(out, out->PackageName, macroExpanders, version);
+ CHECK_EXPAND(out, out->PackageVersion, macroExpanders, version);
+ CHECK_EXPAND(out, out->PackageDirectory, macroExpanders, version);
+ CHECK_EXPAND(out, out->VendorName, macroExpanders, version);
return true;
}
-bool ExpandMacros(cmCMakePresetsGraph const& /*graph*/,
- WorkflowPreset const& /*preset*/,
- cm::optional<WorkflowPreset>& /*out*/,
- MacroExpanderVector const& /*macroExpanders*/)
+bool CheckExpandMacros(WorkflowPreset const& /*preset*/,
+ cm::optional<WorkflowPreset>& /*out*/,
+ MacroExpanderVector const& /*macroExpanders*/,
+ cmCMakePresetsGraph const* /*graph*/ = nullptr)
{
return true;
}
-template <class T>
-bool ExpandMacros(cmCMakePresetsGraph& graph, T const& preset,
+template <typename T>
+bool ExpandMacros(cmCMakePresetsGraph* graph, T const& preset,
cm::optional<T>& out)
{
out.emplace(preset);
@@ -420,23 +442,25 @@
MacroExpanderVector macroExpanders{};
- macroExpanders.push_back(cm::make_unique<BaseMacroExpander>(graph));
+ macroExpanders.push_back(cm::make_unique<BaseMacroExpander>(*graph));
macroExpanders.push_back(
- cm::make_unique<PresetMacroExpander<T>>(graph, preset));
+ cm::make_unique<PresetMacroExpander<T>>(*graph, preset));
macroExpanders.push_back(cm::make_unique<EnvironmentMacroExpander<T>>(
macroExpanders, out, envCycles));
for (auto& v : out->Environment) {
if (v.second) {
switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
- graph.GetVersion(preset))) {
+ graph->GetVersion(preset))) {
case ExpandMacroResult::Error:
cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name,
- &graph.parseState);
+ &graph->parseState);
return false;
case ExpandMacroResult::Ignore:
out.reset();
return true;
+ case ExpandMacroResult::Defer:
+ CM_FALLTHROUGH;
case ExpandMacroResult::Ok:
break;
}
@@ -446,9 +470,9 @@
if (preset.ConditionEvaluator) {
cm::optional<bool> result;
if (!preset.ConditionEvaluator->Evaluate(
- macroExpanders, graph.GetVersion(preset), result)) {
+ macroExpanders, graph->GetVersion(preset), result)) {
cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name,
- &graph.parseState);
+ &graph->parseState);
return false;
}
if (!result) {
@@ -458,7 +482,7 @@
out->ConditionResult = *result;
}
- return ExpandMacros(graph, preset, out, macroExpanders);
+ return CheckExpandMacros(preset, out, macroExpanders, graph);
}
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
@@ -480,8 +504,95 @@
status = CycleStatus::Verified;
return ExpandMacroResult::Ok;
}
+
+void PrintPresets(
+ std::vector<cmCMakePresetsGraph::Preset const*> const& presets)
+{
+ if (presets.empty()) {
+ return;
+ }
+
+ auto presetWithLongestName =
+ std::max_element(presets.begin(), presets.end(),
+ [](cmCMakePresetsGraph::Preset const* a,
+ cmCMakePresetsGraph::Preset const* b) {
+ return a->Name.length() < b->Name.length();
+ });
+ auto longestLength = (*presetWithLongestName)->Name.length();
+
+ for (auto const* preset : presets) {
+ std::string name = cmStrCat(" \"", preset->Name, '"');
+ if (!preset->DisplayName.empty()) {
+ int const width = static_cast<int>(longestLength + name.length() -
+ preset->Name.length());
+ std::cout << std::left << std::setw(width) << name << " - "
+ << preset->DisplayName << '\n';
+ } else {
+ std::cout << name << '\n';
+ }
+ }
}
+struct AlwaysTrue
+{
+ template <typename T>
+ constexpr bool operator()(T const&) const noexcept
+ {
+ return true;
+ }
+};
+
+template <typename PresetType, typename Filter = AlwaysTrue>
+void PrintPresetList(
+ cmCMakePresetsGraph const* const graph,
+ std::map<std::string, cmCMakePresetsGraph::PresetPair<PresetType>>
+ cmCMakePresetsGraph::*data,
+ std::vector<std::string> cmCMakePresetsGraph::*index, Filter filter = {})
+{
+ std::vector<cmCMakePresetsGraph::Preset const*> presets;
+ presets.reserve((graph->*index).size());
+ for (auto const& p : graph->*index) {
+ auto const& preset = (graph->*data).at(p);
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
+ presets.push_back(
+ static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ std::cout << (gSkipNewLine ? "" : "\n") << "Available "
+ << PresetType::kind() << " presets:\n\n";
+ gSkipNewLine = false;
+ PrintPresets(presets);
+ }
+}
+}
+
+template <typename T>
+bool cmCMakePresetsGraphInternal::ExpandImmediateMacros(T& preset)
+{
+ MacroExpanderVector macroExpanders{};
+ macroExpanders.push_back(cm::make_unique<ImmediateMacroExpander<T>>(preset));
+ cm::optional<T> out = preset;
+ bool result = CheckExpandMacros(preset, out, macroExpanders);
+ if (out.has_value()) {
+ preset = out.value();
+ };
+ return result;
+}
+
+template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<
+ ConfigurePreset>(ConfigurePreset&);
+template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<BuildPreset>(
+ BuildPreset&);
+template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<TestPreset>(
+ TestPreset&);
+template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<
+ PackagePreset>(PackagePreset&);
+template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<
+ WorkflowPreset>(WorkflowPreset&);
+
ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros(
std::string& out, MacroExpanderVector const& macroExpanders, int version)
{
@@ -781,17 +892,10 @@
InheritString(preset.InstallDir, parent.InstallDir);
InheritString(preset.ToolchainFile, parent.ToolchainFile);
InheritString(preset.GraphVizFile, parent.GraphVizFile);
- InheritOptionalValue(preset.WarnDev, parent.WarnDev);
- InheritOptionalValue(preset.ErrorDev, parent.ErrorDev);
- InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated);
- InheritOptionalValue(preset.ErrorDeprecated, parent.ErrorDeprecated);
- InheritOptionalValue(preset.WarnUninitialized, parent.WarnUninitialized);
- InheritOptionalValue(preset.WarnUnusedCli, parent.WarnUnusedCli);
+ InheritMap(preset.Warnings, parent.Warnings);
+ InheritMap(preset.Errors, parent.Errors);
InheritOptionalValue(preset.WarnSystemVars, parent.WarnSystemVars);
-
- for (auto const& v : parent.CacheVariables) {
- preset.CacheVariables.insert(v);
- }
+ InheritMap(preset.CacheVariables, parent.CacheVariables);
return true;
}
@@ -824,12 +928,15 @@
}
}
- if (preset.WarnDev == false && preset.ErrorDev == true) {
- return false;
+ for (auto const& w : preset.Warnings) {
+ auto const ei = preset.Errors.find(w.first);
+ if (ei != preset.Errors.end()) {
+ if (w.second == false && ei->second == true) {
+ return false;
+ }
+ }
}
- if (preset.WarnDeprecated == false && preset.ErrorDeprecated == true) {
- return false;
- }
+
if (preset.CacheVariables.count("") != 0) {
return false;
}
@@ -863,11 +970,7 @@
bool cmCMakePresetsGraph::BuildPreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*stat*/)
{
- auto& preset = *this;
- if (!preset.Hidden && preset.ConfigurePreset.empty()) {
- return false;
- }
- return true;
+ return this->Hidden || !this->ConfigurePreset.empty();
}
bool cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
@@ -964,6 +1067,8 @@
InheritOptionalValue(execution.Timeout, parentExecution.Timeout);
InheritOptionalValue(execution.NoTestsAction,
parentExecution.NoTestsAction);
+ InheritVector(execution.TestPassthroughArguments,
+ parentExecution.TestPassthroughArguments);
} else {
preset.Execution = parent.Execution;
}
@@ -975,11 +1080,7 @@
bool cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*state*/)
{
- auto& preset = *this;
- if (!preset.Hidden && preset.ConfigurePreset.empty()) {
- return false;
- }
- return true;
+ return this->Hidden || !this->ConfigurePreset.empty();
}
bool cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
@@ -994,11 +1095,7 @@
parent.InheritConfigureEnvironment);
InheritVector(preset.Generators, parent.Generators);
InheritVector(preset.Configurations, parent.Configurations);
-
- for (auto const& v : parent.Variables) {
- preset.Variables.insert(v);
- }
-
+ InheritMap(preset.Variables, parent.Variables);
InheritOptionalValue(preset.DebugOutput, parent.DebugOutput);
InheritOptionalValue(preset.VerboseOutput, parent.VerboseOutput);
InheritString(preset.PackageName, parent.PackageName);
@@ -1012,11 +1109,7 @@
bool cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*state*/)
{
- auto& preset = *this;
- if (!preset.Hidden && preset.ConfigurePreset.empty()) {
- return false;
- }
- return true;
+ return this->Hidden || !this->ConfigurePreset.empty();
}
bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
@@ -1055,6 +1148,34 @@
return true;
}
+std::string cmCMakePresetsGraph::GetGeneratorForPreset(
+ std::string const& presetName) const
+{
+ auto configurePresetName = presetName;
+
+ auto buildPresetIterator = this->BuildPresets.find(presetName);
+ if (buildPresetIterator != this->BuildPresets.end()) {
+ configurePresetName =
+ buildPresetIterator->second.Unexpanded.ConfigurePreset;
+ } else {
+ auto testPresetIterator = this->TestPresets.find(presetName);
+ if (testPresetIterator != this->TestPresets.end()) {
+ configurePresetName =
+ testPresetIterator->second.Unexpanded.ConfigurePreset;
+ }
+ }
+
+ auto configurePresetIterator =
+ this->ConfigurePresets.find(configurePresetName);
+ if (configurePresetIterator != this->ConfigurePresets.end()) {
+ return configurePresetIterator->second.Unexpanded.Generator;
+ }
+
+ // This should only happen if the preset is hidden
+ // or (for build or test presets) if ConfigurePreset is invalid.
+ return {};
+}
+
bool cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
{
bool haveOneFile = false;
@@ -1098,7 +1219,7 @@
}
for (auto& it : this->ConfigurePresets) {
- if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
@@ -1128,7 +1249,7 @@
}
}
- if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
@@ -1158,7 +1279,7 @@
}
}
- if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
@@ -1188,7 +1309,7 @@
}
}
- if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
@@ -1243,7 +1364,7 @@
return false;
}
- if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
@@ -1270,166 +1391,58 @@
this->Files.clear();
}
-void cmCMakePresetsGraph::printPrecedingNewline(PrintPrecedingNewline* newline)
+void cmCMakePresetsGraph::PrintConfigurePresetList() const
{
- if (newline) {
- if (*newline == PrintPrecedingNewline::True) {
- std::cout << std::endl;
- }
- *newline = PrintPrecedingNewline::True;
- }
-}
-
-void cmCMakePresetsGraph::PrintPresets(
- std::vector<cmCMakePresetsGraph::Preset const*> const& presets)
-{
- if (presets.empty()) {
- return;
- }
-
- auto longestPresetName =
- std::max_element(presets.begin(), presets.end(),
- [](cmCMakePresetsGraph::Preset const* a,
- cmCMakePresetsGraph::Preset const* b) {
- return a->Name.length() < b->Name.length();
- });
- auto longestLength = (*longestPresetName)->Name.length();
-
- for (auto const* preset : presets) {
- std::cout << " \"" << preset->Name << '"';
- auto const& description = preset->DisplayName;
- if (!description.empty()) {
- for (std::size_t i = 0; i < longestLength - preset->Name.length(); ++i) {
- std::cout << ' ';
- }
- std::cout << " - " << description;
- }
- std::cout << '\n';
- }
+ PrintPresetList<ConfigurePreset>(this,
+ &cmCMakePresetsGraph::ConfigurePresets,
+ &cmCMakePresetsGraph::ConfigurePresetOrder);
}
void cmCMakePresetsGraph::PrintConfigurePresetList(
- PrintPrecedingNewline* newline) const
+ std::function<bool(ConfigurePreset const&)> const& filter) const
{
- PrintConfigurePresetList([](ConfigurePreset const&) { return true; },
- newline);
+ PrintPresetList<ConfigurePreset>(
+ this, &cmCMakePresetsGraph::ConfigurePresets,
+ &cmCMakePresetsGraph::ConfigurePresetOrder, filter);
}
-void cmCMakePresetsGraph::PrintConfigurePresetList(
- std::function<bool(ConfigurePreset const&)> const& filter,
- PrintPrecedingNewline* newline) const
+void cmCMakePresetsGraph::PrintBuildPresetList() const
{
- std::vector<cmCMakePresetsGraph::Preset const*> presets;
- for (auto const& p : this->ConfigurePresetOrder) {
- auto const& preset = this->ConfigurePresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded &&
- preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
- presets.push_back(
- static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
- }
- }
-
- if (!presets.empty()) {
- printPrecedingNewline(newline);
- std::cout << "Available configure presets:\n\n";
- cmCMakePresetsGraph::PrintPresets(presets);
- }
+ PrintPresetList<BuildPreset>(this, &cmCMakePresetsGraph::BuildPresets,
+ &cmCMakePresetsGraph::BuildPresetOrder);
}
-void cmCMakePresetsGraph::PrintBuildPresetList(
- PrintPrecedingNewline* newline) const
+void cmCMakePresetsGraph::PrintTestPresetList() const
{
- std::vector<cmCMakePresetsGraph::Preset const*> presets;
- for (auto const& p : this->BuildPresetOrder) {
- auto const& preset = this->BuildPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded &&
- preset.Expanded->ConditionResult) {
- presets.push_back(
- static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
- }
- }
-
- if (!presets.empty()) {
- printPrecedingNewline(newline);
- std::cout << "Available build presets:\n\n";
- cmCMakePresetsGraph::PrintPresets(presets);
- }
+ PrintPresetList<TestPreset>(this, &cmCMakePresetsGraph::TestPresets,
+ &cmCMakePresetsGraph::TestPresetOrder);
}
-void cmCMakePresetsGraph::PrintTestPresetList(
- PrintPrecedingNewline* newline) const
+void cmCMakePresetsGraph::PrintPackagePresetList() const
{
- std::vector<cmCMakePresetsGraph::Preset const*> presets;
- for (auto const& p : this->TestPresetOrder) {
- auto const& preset = this->TestPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded &&
- preset.Expanded->ConditionResult) {
- presets.push_back(
- static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
- }
- }
-
- if (!presets.empty()) {
- printPrecedingNewline(newline);
- std::cout << "Available test presets:\n\n";
- cmCMakePresetsGraph::PrintPresets(presets);
- }
+ PrintPresetList<PackagePreset>(this, &cmCMakePresetsGraph::PackagePresets,
+ &cmCMakePresetsGraph::PackagePresetOrder);
}
void cmCMakePresetsGraph::PrintPackagePresetList(
- PrintPrecedingNewline* newline) const
+ std::function<bool(PackagePreset const&)> const& filter) const
{
- this->PrintPackagePresetList([](PackagePreset const&) { return true; },
- newline);
+ PrintPresetList<PackagePreset>(this, &cmCMakePresetsGraph::PackagePresets,
+ &cmCMakePresetsGraph::PackagePresetOrder,
+ filter);
}
-void cmCMakePresetsGraph::PrintPackagePresetList(
- std::function<bool(PackagePreset const&)> const& filter,
- PrintPrecedingNewline* newline) const
+void cmCMakePresetsGraph::PrintWorkflowPresetList() const
{
- std::vector<cmCMakePresetsGraph::Preset const*> presets;
- for (auto const& p : this->PackagePresetOrder) {
- auto const& preset = this->PackagePresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded &&
- preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
- presets.push_back(
- static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
- }
- }
-
- if (!presets.empty()) {
- printPrecedingNewline(newline);
- std::cout << "Available package presets:\n\n";
- cmCMakePresetsGraph::PrintPresets(presets);
- }
-}
-
-void cmCMakePresetsGraph::PrintWorkflowPresetList(
- PrintPrecedingNewline* newline) const
-{
- std::vector<cmCMakePresetsGraph::Preset const*> presets;
- for (auto const& p : this->WorkflowPresetOrder) {
- auto const& preset = this->WorkflowPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded &&
- preset.Expanded->ConditionResult) {
- presets.push_back(
- static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
- }
- }
-
- if (!presets.empty()) {
- printPrecedingNewline(newline);
- std::cout << "Available workflow presets:\n\n";
- cmCMakePresetsGraph::PrintPresets(presets);
- }
+ PrintPresetList<WorkflowPreset>(this, &cmCMakePresetsGraph::WorkflowPresets,
+ &cmCMakePresetsGraph::WorkflowPresetOrder);
}
void cmCMakePresetsGraph::PrintAllPresets() const
{
- PrintPrecedingNewline newline = PrintPrecedingNewline::False;
- this->PrintConfigurePresetList(&newline);
- this->PrintBuildPresetList(&newline);
- this->PrintTestPresetList(&newline);
- this->PrintPackagePresetList(&newline);
- this->PrintWorkflowPresetList(&newline);
+ this->PrintConfigurePresetList();
+ this->PrintBuildPresetList();
+ this->PrintTestPresetList();
+ this->PrintPackagePresetList();
+ this->PrintWorkflowPresetList();
}
diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h
index 4ce0ace..7ee529f 100644
--- a/Source/cmCMakePresetsGraph.h
+++ b/Source/cmCMakePresetsGraph.h
@@ -9,11 +9,11 @@
#include <memory>
#include <string>
#include <unordered_set>
-#include <utility>
#include <vector>
#include <cm/optional>
+#include "cmDiagnostics.h"
#include "cmJSONState.h"
#include "cmStateTypes.h" // IWYU pragma: keep
@@ -40,22 +40,19 @@
Expand,
};
- class CacheVariable
+ struct CacheVariable
{
- public:
std::string Type;
std::string Value;
};
class Condition;
- class File
+ struct File
{
- public:
+ std::unordered_set<File*> ReachableFiles;
std::string Filename;
int Version;
-
- std::unordered_set<File*> ReachableFiles;
};
class Preset
@@ -126,13 +123,11 @@
std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
- cm::optional<bool> WarnDev;
- cm::optional<bool> ErrorDev;
- cm::optional<bool> WarnDeprecated;
- cm::optional<bool> ErrorDeprecated;
- cm::optional<bool> WarnUninitialized;
- cm::optional<bool> WarnUnusedCli;
+ std::map<cmDiagnosticCategory, bool> Warnings;
+ std::map<cmDiagnosticCategory, bool> Errors;
cm::optional<bool> WarnSystemVars;
+ cm::optional<bool> WarnDev; // Deprecated synonym for Warnings.CMD_AUTHOR
+ cm::optional<bool> ErrorDev; // Deprecated synonym for Errors.CMD_AUTHOR
cm::optional<bool> DebugOutput;
cm::optional<bool> DebugTryCompile;
@@ -146,6 +141,8 @@
bool VisitPresetInherit(Preset const& parent) override;
bool VisitPresetBeforeInherit() override;
bool VisitPresetAfterInherit(int version, cmJSONState* state) override;
+
+ static char const* kind() { return "configure"; }
};
class BuildPreset : public Preset
@@ -178,6 +175,8 @@
bool VisitPresetInherit(Preset const& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/) override;
+
+ static char const* kind() { return "build"; }
};
class TestPreset : public Preset
@@ -299,6 +298,7 @@
cm::optional<bool> ScheduleRandom;
cm::optional<int> Timeout;
cm::optional<NoTestsActionEnum> NoTestsAction;
+ std::vector<std::string> TestPassthroughArguments;
};
std::string ConfigurePreset;
@@ -312,6 +312,8 @@
bool VisitPresetInherit(Preset const& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/) override;
+
+ static char const* kind() { return "test"; }
};
class PackagePreset : public Preset
@@ -349,6 +351,8 @@
bool VisitPresetInherit(Preset const& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/) override;
+
+ static char const* kind() { return "package"; }
};
class WorkflowPreset : public Preset
@@ -368,9 +372,8 @@
WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = delete;
#endif
- class WorkflowStep
+ struct WorkflowStep
{
- public:
enum class Type
{
Configure,
@@ -387,12 +390,13 @@
bool VisitPresetInherit(Preset const& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /* state */) override;
+
+ static char const* kind() { return "workflow"; }
};
- template <class T>
- class PresetPair
+ template <typename T>
+ struct PresetPair
{
- public:
T Unexpanded;
cm::optional<T> Expanded;
};
@@ -417,59 +421,20 @@
return preset.OriginFile->Version;
}
- static std::string GetFilename(std::string const& sourceDir);
- static std::string GetUserFilename(std::string const& sourceDir);
bool ReadProjectPresets(std::string const& sourceDir,
bool allowNoFiles = false);
- std::string GetGeneratorForPreset(std::string const& presetName) const
- {
- auto configurePresetName = presetName;
+ std::string GetGeneratorForPreset(std::string const& presetName) const;
- auto buildPresetIterator = this->BuildPresets.find(presetName);
- if (buildPresetIterator != this->BuildPresets.end()) {
- configurePresetName =
- buildPresetIterator->second.Unexpanded.ConfigurePreset;
- } else {
- auto testPresetIterator = this->TestPresets.find(presetName);
- if (testPresetIterator != this->TestPresets.end()) {
- configurePresetName =
- testPresetIterator->second.Unexpanded.ConfigurePreset;
- }
- }
-
- auto configurePresetIterator =
- this->ConfigurePresets.find(configurePresetName);
- if (configurePresetIterator != this->ConfigurePresets.end()) {
- return configurePresetIterator->second.Unexpanded.Generator;
- }
-
- // This should only happen if the preset is hidden
- // or (for build or test presets) if ConfigurePreset is invalid.
- return "";
- }
-
- enum class PrintPrecedingNewline
- {
- False,
- True,
- };
- static void printPrecedingNewline(PrintPrecedingNewline* p);
-
- static void PrintPresets(
- std::vector<cmCMakePresetsGraph::Preset const*> const& presets);
+ void PrintConfigurePresetList() const;
void PrintConfigurePresetList(
- PrintPrecedingNewline* newline = nullptr) const;
- void PrintConfigurePresetList(
- std::function<bool(ConfigurePreset const&)> const& filter,
- PrintPrecedingNewline* newline = nullptr) const;
- void PrintBuildPresetList(PrintPrecedingNewline* newline = nullptr) const;
- void PrintTestPresetList(PrintPrecedingNewline* newline = nullptr) const;
- void PrintPackagePresetList(PrintPrecedingNewline* newline = nullptr) const;
+ std::function<bool(ConfigurePreset const&)> const& filter) const;
+ void PrintBuildPresetList() const;
+ void PrintTestPresetList() const;
+ void PrintPackagePresetList() const;
void PrintPackagePresetList(
- std::function<bool(PackagePreset const&)> const& filter,
- PrintPrecedingNewline* newline = nullptr) const;
- void PrintWorkflowPresetList(PrintPrecedingNewline* newline = nullptr) const;
+ std::function<bool(PackagePreset const&)> const& filter) const;
+ void PrintWorkflowPresetList() const;
void PrintAllPresets() const;
private:
@@ -490,4 +455,7 @@
ReadReason readReason, std::vector<File*>& inProgressFiles,
File*& file, std::string& errMsg);
void ClearPresets();
+
+ static std::string GetFilename(std::string const& sourceDir);
+ static std::string GetUserFilename(std::string const& sourceDir);
};
diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h
index 02c99ee..772a3d4 100644
--- a/Source/cmCMakePresetsGraphInternal.h
+++ b/Source/cmCMakePresetsGraphInternal.h
@@ -7,6 +7,8 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
#include <cm3p/json/value.h>
#include "cmCMakePresetsGraph.h"
@@ -25,6 +27,7 @@
{
Ok,
Ignore,
+ Defer,
Error,
};
@@ -83,7 +86,7 @@
int version) const override;
};
-template <class T>
+template <typename T>
class PresetMacroExpander : public MacroExpander
{
cmCMakePresetsGraph const& Graph;
@@ -125,6 +128,49 @@
}
};
+template <class T>
+class ImmediateMacroExpander : public MacroExpander
+{
+ T const& Preset;
+
+public:
+ ImmediateMacroExpander(T const& preset)
+ : Preset(preset)
+ {
+ }
+ ExpandMacroResult operator()(std::string const& macroNamespace,
+ std::string const& macroName,
+ std::string& macroOut,
+ int version) const override
+ {
+ if (macroNamespace.empty()) {
+ if (macroName == "fileDir") {
+ if (version < 12) {
+ return ExpandMacroResult::Defer;
+ }
+ macroOut +=
+ cmSystemTools::GetParentDirectory(Preset.OriginFile->Filename);
+ return ExpandMacroResult::Ok;
+ }
+ }
+ return ExpandMacroResult::Defer;
+ }
+};
+
+template <typename T>
+bool ExpandImmediateMacros(T& preset);
+
+extern template bool ExpandImmediateMacros<
+ cmCMakePresetsGraph::ConfigurePreset>(cmCMakePresetsGraph::ConfigurePreset&);
+extern template bool ExpandImmediateMacros<cmCMakePresetsGraph::BuildPreset>(
+ cmCMakePresetsGraph::BuildPreset&);
+extern template bool ExpandImmediateMacros<cmCMakePresetsGraph::TestPreset>(
+ cmCMakePresetsGraph::TestPreset&);
+extern template bool ExpandImmediateMacros<cmCMakePresetsGraph::PackagePreset>(
+ cmCMakePresetsGraph::PackagePreset&);
+extern template bool ExpandImmediateMacros<
+ cmCMakePresetsGraph::WorkflowPreset>(cmCMakePresetsGraph::WorkflowPreset&);
+
class NullCondition : public cmCMakePresetsGraph::Condition
{
bool Evaluate(MacroExpanderVector const& /*expanders*/, int /*version*/,
@@ -213,6 +259,22 @@
bool PresetOptionalBoolHelper(cm::optional<bool>& out,
Json::Value const* value, cmJSONState* state);
+template <typename K>
+bool PresetMapToBoolHelper(std::map<K, bool>& out, Json::Value const* value,
+ K key, cmJSONState* state)
+{
+ cm::optional<bool> temp;
+ if (!PresetOptionalBoolHelper(temp, value, state)) {
+ return false;
+ }
+
+ if (temp) {
+ out[key] = *temp;
+ }
+
+ return true;
+}
+
bool PresetIntHelper(int& out, Json::Value const* value, cmJSONState* state);
bool PresetOptionalIntHelper(cm::optional<int>& out, Json::Value const* value,
@@ -259,4 +321,7 @@
Json::Value const* value, cmJSONState* state);
cmJSONHelper<std::nullptr_t> SchemaHelper();
+
+bool CheckDiagnostics(cmJSONState* state, int version,
+ cmCMakePresetsGraph::ConfigurePreset& preset);
}
diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx
index d141b10..27c3b99 100644
--- a/Source/cmCMakePresetsGraphReadJSON.cxx
+++ b/Source/cmCMakePresetsGraphReadJSON.cxx
@@ -38,9 +38,10 @@
using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector;
using cmCMakePresetsGraphInternal::BaseMacroExpander;
using cmCMakePresetsGraphInternal::ExpandMacros;
+using cmCMakePresetsGraphInternal::ExpandImmediateMacros;
constexpr int MIN_VERSION = 1;
-constexpr int MAX_VERSION = 11;
+constexpr int MAX_VERSION = 12;
struct CMakeVersion
{
@@ -591,11 +592,9 @@
return false;
}
- PresetPair<ConfigurePreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->ConfigurePresets.emplace(preset.Name, presetPair).second) {
- cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
+ if (!ExpandImmediateMacros<ConfigurePreset>(preset)) {
+ cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
+ &this->parseState);
return false;
}
@@ -632,6 +631,20 @@
return false;
}
+ // Support for diagnostics.
+ if (!cmCMakePresetsGraphInternal::CheckDiagnostics(&this->parseState, v,
+ preset)) {
+ return false;
+ }
+
+ PresetPair<ConfigurePreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->ConfigurePresets.emplace(preset.Name, presetPair).second) {
+ cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
+ return false;
+ }
+
this->ConfigurePresetOrder.push_back(preset.Name);
}
@@ -642,6 +655,12 @@
return false;
}
+ if (!ExpandImmediateMacros<BuildPreset>(preset)) {
+ cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
+ &this->parseState);
+ return false;
+ }
+
PresetPair<BuildPreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
@@ -666,6 +685,12 @@
return false;
}
+ if (!ExpandImmediateMacros<TestPreset>(preset)) {
+ cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
+ &this->parseState);
+ return false;
+ }
+
PresetPair<TestPreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
@@ -700,6 +725,13 @@
return false;
}
+ // Support for testPassthroughArguments added in version 12.
+ if (v < 12 && preset.Execution &&
+ !preset.Execution->TestPassthroughArguments.empty()) {
+ cmCMakePresetsErrors::PASSTHROUGH_ARGS_UNSUPPORTED(&this->parseState);
+ return false;
+ }
+
this->TestPresetOrder.push_back(preset.Name);
}
@@ -710,6 +742,12 @@
return false;
}
+ if (!ExpandImmediateMacros<PackagePreset>(preset)) {
+ cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
+ &this->parseState);
+ return false;
+ }
+
PresetPair<PackagePreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
@@ -731,6 +769,12 @@
return false;
}
+ if (!ExpandImmediateMacros<WorkflowPreset>(preset)) {
+ cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
+ &this->parseState);
+ return false;
+ }
+
PresetPair<WorkflowPreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
diff --git a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx
index 5b62d09..9298fda 100644
--- a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx
+++ b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx
@@ -1,20 +1,27 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
+#include <cassert>
#include <cstddef>
#include <functional>
#include <map>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/algorithm>
#include <cmext/string_view>
#include <cm3p/json/value.h>
+#include "cmsys/String.h"
+
#include "cmCMakePresetsErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
+#include "cmDiagnostics.h"
#include "cmJSONHelpers.h"
#include "cmStateTypes.h"
@@ -204,27 +211,68 @@
JSONHelperBuilder::Map<cm::optional<CacheVariable>>(
cmCMakePresetsErrors::INVALID_PRESET, VariableHelper);
+template <cmDiagnosticCategory C>
+cm::string_view GetJSONName()
+{
+ static std::string storage = [] {
+ cm::string_view const in = cmDiagnostics::GetCategoryString(C).substr(4);
+ std::string out;
+ bool sep = false;
+ for (char const c : in) {
+ if (sep) {
+ out += c;
+ sep = false;
+ } else if (c == '_') {
+ sep = true;
+ } else {
+ out += static_cast<char>(cmsysString_tolower(c));
+ }
+ }
+ return out;
+ }();
+ return storage;
+}
+
+cm::string_view GetJSONName(cmDiagnosticCategory category)
+{
+ static cm::string_view const names[] = {
+ "none"_s, // CMD_NONE
+#define DIAGNOSTIC_JSON_NAME(C) GetJSONName<cmDiagnostics::C>(),
+ CM_FOR_EACH_DIAGNOSTIC_CATEGORY(DIAGNOSTIC_JSON_NAME)
+#undef DIAGNOSTIC_JSON_NAME
+ };
+ assert(category > 0 && category < cmDiagnostics::CategoryCount);
+ return names[category];
+}
+
+auto const PresetDiagnosticMapHelper =
+ cmCMakePresetsGraphInternal::PresetMapToBoolHelper<cmDiagnosticCategory>;
+
+#define BIND_DIAGNOSTIC(C) \
+ .Bind(GetJSONName<cmDiagnostics::C>(), &DIAGNOSTIC_MEMBER, \
+ PresetDiagnosticMapHelper, cmDiagnostics::C, false)
+
+#define DIAGNOSTIC_MEMBER ConfigurePreset::Warnings
auto const PresetWarningsHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
JsonErrors::INVALID_NAMED_OBJECT_KEY, false)
.Bind("dev"_s, &ConfigurePreset::WarnDev,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
- cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
- .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
- cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
- .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
- cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ CM_FOR_EACH_DIAGNOSTIC_CATEGORY(BIND_DIAGNOSTIC)
.Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+#undef DIAGNOSTIC_MEMBER
+#define DIAGNOSTIC_MEMBER ConfigurePreset::Errors
auto const PresetErrorsHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
JsonErrors::INVALID_NAMED_OBJECT_KEY, false)
.Bind("dev"_s, &ConfigurePreset::ErrorDev,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
- cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+ CM_FOR_EACH_DIAGNOSTIC_CATEGORY(BIND_DIAGNOSTIC);
+#undef DIAGNOSTIC_MEMBER
+
+#undef BIND_DIAGNOSTIC
auto const PresetDebugHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
@@ -301,4 +349,71 @@
return helper(out, value, state);
}
+
+bool CheckDiagnostics(cmJSONState* state, int version,
+ std::map<cmDiagnosticCategory, bool> values,
+ cm::string_view group)
+{
+ // NOLINTNEXTLINE(readability-use-anyofallof)
+ for (auto const& i : values) {
+ assert(i.first > 0 && i.first < cmDiagnostics::CategoryCount);
+ int const minVersion = cmDiagnostics::CategoryInfo[i.first].PresetVersion;
+ if (version < minVersion) {
+ cm::string_view dn = GetJSONName(i.first);
+ cmCMakePresetsErrors::DIAGNOSTIC_UNSUPPORTED(dn, group, minVersion,
+ state);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CheckDiagnostics(cmJSONState* state, int version,
+ cmCMakePresetsGraph::ConfigurePreset& preset)
+{
+ // Check for diagnostics added in later schemes.
+ if (!CheckDiagnostics(state, version, preset.Warnings, "warnings"_s) ||
+ !CheckDiagnostics(state, version, preset.Errors, "errors"_s)) {
+ return false;
+ }
+
+ if (version < 12) {
+ // Handle 'dev'.
+ if (preset.WarnDev) {
+ preset.Warnings.emplace(cmDiagnostics::CMD_AUTHOR, *preset.WarnDev);
+ }
+ if (preset.ErrorDev) {
+ preset.Errors.emplace(cmDiagnostics::CMD_AUTHOR, *preset.ErrorDev);
+ }
+
+ // Check for diagnostics only present as warnings before v12.
+ constexpr cmDiagnosticCategory unsupportedErrors[] = {
+ cmDiagnostics::CMD_UNINITIALIZED,
+ cmDiagnostics::CMD_UNUSED_CLI,
+ };
+
+ for (cmDiagnosticCategory c : unsupportedErrors) {
+ if (cm::contains(preset.Errors, c)) {
+ cm::string_view dn = GetJSONName(c);
+ cmCMakePresetsErrors::DIAGNOSTIC_UNSUPPORTED(dn, "errors"_s, 12,
+ state);
+ return false;
+ }
+ }
+ } else {
+ // Check for diagnostics removed in v12.
+ if (preset.WarnDev) {
+ cmCMakePresetsErrors::DIAGNOSTIC_REMOVED("dev"_s, "warnings"_s, 11,
+ state);
+ return false;
+ }
+ if (preset.ErrorDev) {
+ cmCMakePresetsErrors::DIAGNOSTIC_REMOVED("dev"_s, "errors"_s, 11, state);
+ return false;
+ }
+ }
+
+ return true;
+}
}
diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
index d716445..050c701 100644
--- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
+++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
@@ -353,7 +353,10 @@
.Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
.Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
- TestPresetOptionalExecutionNoTestsActionHelper, false));
+ TestPresetOptionalExecutionNoTestsActionHelper, false)
+ .Bind("testPassthroughArguments"_s,
+ &TestPreset::ExecutionOptions::TestPassthroughArguments,
+ cmCMakePresetsGraphInternal::PresetVectorStringHelper, false));
auto const TestPresetFilterHelper =
JSONHelperBuilder::Optional<TestPreset::FilterOptions>(
diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx
index db33bba..6193ede 100644
--- a/Source/cmCPackPropertiesGenerator.cxx
+++ b/Source/cmCPackPropertiesGenerator.cxx
@@ -1,11 +1,11 @@
#include "cmCPackPropertiesGenerator.h"
#include <map>
+#include <memory>
#include <ostream>
#include "cmGeneratorExpression.h"
#include "cmInstalledFile.h"
-#include "cmOutputConverter.h"
cmCPackPropertiesGenerator::cmCPackPropertiesGenerator(
cmLocalGenerator* lg, cmInstalledFile const& installedFile,
@@ -31,13 +31,11 @@
cmInstalledFile::Property const& property = i.second;
os << indent << "set_property(INSTALL "
- << cmOutputConverter::EscapeForCMake(expandedFileName) << " PROPERTY "
- << cmOutputConverter::EscapeForCMake(name);
+ << cmScriptGenerator::Quote(expandedFileName) << " PROPERTY "
+ << cmScriptGenerator::Quote(name);
- for (cmInstalledFile::ExpressionVectorType::value_type const& j :
- property.ValueExpressions) {
- std::string value = j->Evaluate(this->LG, config);
- os << " " << cmOutputConverter::EscapeForCMake(value);
+ for (auto const& j : property.ValueExpressions) {
+ os << ' ' << cmScriptGenerator::Quote(j->Evaluate(this->LG, config));
}
os << ")\n";
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index ed1516f..705a5bd 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -12,6 +12,7 @@
#include <functional>
#include <initializer_list>
#include <iostream>
+#include <iterator>
#include <map>
#include <ratio>
#include <sstream>
@@ -821,7 +822,7 @@
d.Load(notes_dir);
unsigned long kk;
for (kk = 0; kk < d.GetNumberOfFiles(); kk++) {
- char const* file = d.GetFile(kk);
+ std::string const& file = d.GetFileName(kk);
std::string fullname = cmStrCat(notes_dir, '/', file);
if (cmSystemTools::FileExists(fullname, true)) {
if (!this->Impl->NotesFiles.empty()) {
@@ -1251,8 +1252,8 @@
std::vector<std::string> files;
files.push_back(file);
- if (!cmSystemTools::CreateTar(tarFile, files, {},
- cmSystemTools::TarCompressGZip, false)) {
+ if (!cmSystemTools::CreateTar(
+ tarFile, files, {}, cmSystemTools::TarCompressGZip, "UTF-8", false)) {
cmCTestLog(this, ERROR_MESSAGE,
"Error creating tar while "
"encoding file: "
@@ -1799,6 +1800,11 @@
return false;
}
}
+
+ // Assign passthrough arguments from preset.
+ // CLI -- args (parsed later in Run()) will be appended after these.
+ this->Impl->TestOptions.TestPassthroughArguments =
+ expandedPreset->Execution->TestPassthroughArguments;
}
return true;
@@ -1812,47 +1818,12 @@
bool processSteps = false;
bool SRArgumentSpecified = false;
std::vector<std::pair<std::string, bool>> runScripts;
+ bool listPresets = false;
+ std::string presetName;
// copy the command line
cm::append(this->Impl->InitialCommandLineArguments, args);
- // check if a test preset was specified
-
- bool listPresets =
- find(args.begin(), args.end(), "--list-presets") != args.end();
- auto it =
- std::find_if(args.begin(), args.end(), [](std::string const& arg) -> bool {
- return arg == "--preset" || cmHasLiteralPrefix(arg, "--preset=");
- });
- if (listPresets || it != args.end()) {
- std::string errormsg;
- bool success;
-
- if (listPresets) {
- // If listing presets we don't need a presetName
- success = this->SetArgsFromPreset("", listPresets);
- } else {
- if (cmHasLiteralPrefix(*it, "--preset=")) {
- auto const& presetName = it->substr(9);
- success = this->SetArgsFromPreset(presetName, listPresets);
- } else if (++it != args.end()) {
- auto const& presetName = *it;
- success = this->SetArgsFromPreset(presetName, listPresets);
- } else {
- cmSystemTools::Error("'--preset' requires an argument");
- success = false;
- }
- }
-
- if (listPresets) {
- return success ? 0 : 1;
- }
-
- if (!success) {
- return 1;
- }
- }
-
auto const dashD = [this, &processSteps](std::string const& targ) -> bool {
// AddTestsForDashboard parses the dashboard type and converts it
// into the separate stages
@@ -2034,6 +2005,23 @@
using CommandArgument =
cmCommandLineArgument<bool(std::string const& value)>;
+ auto const presetArguments = std::vector<CommandArgument>{
+ CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
+ [&listPresets](std::string const&) -> bool {
+ listPresets = true;
+ return true;
+ } },
+ CommandArgument{ "--preset", "'--preset' requires an argument",
+ CommandArgument::Values::One,
+ [&presetName](std::string const& presetArg) -> bool {
+ presetName = presetArg;
+ return true;
+ } }
+ };
+ auto const isPresetArgument = [&](std::string const& arg) -> bool {
+ return cmHasLiteralPrefix(arg, "--preset") || arg == "--list-presets";
+ };
+
auto const arguments = std::vector<CommandArgument>{
CommandArgument{ "--dashboard", CommandArgument::Values::One, dashD },
CommandArgument{ "-D",
@@ -2505,9 +2493,45 @@
} },
};
- // process the command line arguments
+ // Process command line arguments for presets first, since other arguments
+ // can override those settings.
for (size_t i = 1; i < args.size(); ++i) {
std::string const& arg = args[i];
+ for (auto const& m : presetArguments) {
+ if (m.matches(arg)) {
+ if (!m.parse(arg, i, args)) {
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+
+ if (listPresets || !presetName.empty()) {
+ bool success = this->SetArgsFromPreset(presetName, listPresets);
+ if (listPresets) {
+ return static_cast<int>(!success);
+ }
+ if (!success) {
+ return 1;
+ }
+ }
+
+ // Process the remaining command line arguments.
+ bool hadPassthroughDelimiter = false;
+ for (size_t i = 1; i < args.size(); ++i) {
+ std::string const& arg = args[i];
+
+ // The "--" argument terminates processing and passes
+ // all remaining arguments through to the tests.
+ if (arg == "--"_s) {
+ hadPassthroughDelimiter = true;
+ std::copy(
+ args.begin() + i + 1, args.end(),
+ std::back_inserter(this->Impl->TestOptions.TestPassthroughArguments));
+ break;
+ }
+
bool matched = false;
for (auto const& m : arguments) {
if (m.matches(arg)) {
@@ -2535,8 +2559,7 @@
this->Impl->BuildAndTest.TestCommandArgs.emplace_back(args[i]);
}
}
- if (!matched && cmHasPrefix(arg, '-') &&
- !cmHasLiteralPrefix(arg, "--preset")) {
+ if (!matched && cmHasPrefix(arg, '-') && !isPresetArgument(arg)) {
cmSystemTools::Error(cmStrCat("Unknown argument: ", arg));
cmSystemTools::Error("Run 'ctest --help' for all supported options.");
return 1;
@@ -2580,6 +2603,27 @@
}
}
+ // Passthrough arguments (after --) are only supported in direct test
+ // execution mode, not --build-and-test, -S, or -D/-T/-M modes.
+ if (hadPassthroughDelimiter) {
+ if (cmakeAndTest) {
+ cmSystemTools::Error(
+ "The -- option cannot be used with --build-and-test. "
+ "Use --build-options or --test-command to forward arguments.");
+ return 1;
+ }
+ if (!runScripts.empty()) {
+ cmSystemTools::Error(
+ "The -- option cannot be used with -S or -SP script mode.");
+ return 1;
+ }
+ if (processSteps) {
+ cmSystemTools::Error(
+ "The -- option cannot be used with -D, -T, or -M dashboard mode.");
+ return 1;
+ }
+ }
+
// TestProgressOutput only supported if console supports it and not logging
// to a file
this->Impl->TestProgressOutput = this->Impl->TestProgressOutput &&
@@ -3654,7 +3698,7 @@
for (unsigned int i = 0; i < d.GetNumberOfFiles(); i++) {
std::string fpath = d.GetFilePath(i);
- std::string fname = d.GetFile(i);
+ std::string const& fname = d.GetFileName(i);
if (fname.rfind('.', 0) == 0) {
continue;
}
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 498c1b5..9e0d2e4 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -17,6 +17,7 @@
#include "cmBlockCommand.h"
#include "cmBreakCommand.h"
#include "cmBuildCommand.h"
+#include "cmCMakeDiagnosticCommand.h"
#include "cmCMakeLanguageCommand.h"
#include "cmCMakeMinimumRequired.h"
#include "cmCMakePathCommand.h"
@@ -25,6 +26,7 @@
#include "cmContinueCommand.h"
#include "cmCreateTestSourceList.h"
#include "cmDefinePropertyCommand.h"
+#include "cmDiscoverTestsCommand.h"
#include "cmEnableLanguageCommand.h"
#include "cmEnableTestingCommand.h"
#include "cmExecProgramCommand.h"
@@ -124,6 +126,7 @@
state->AddFlowControlCommand("while", cmWhileCommand);
state->AddFlowControlCommand("block", cmBlockCommand);
+ state->AddBuiltinCommand("cmake_diagnostic", cmCMakeDiagnosticCommand);
state->AddBuiltinCommand("cmake_language", cmCMakeLanguageCommand);
state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired);
state->AddBuiltinCommand("cmake_path", cmCMakePathCommand);
@@ -237,6 +240,7 @@
state->AddBuiltinCommand("build_command", cmBuildCommand);
state->AddBuiltinCommand("create_test_sourcelist", cmCreateTestSourceList);
state->AddBuiltinCommand("define_property", cmDefinePropertyCommand);
+ state->AddBuiltinCommand("discover_tests", cmDiscoverTestsCommand);
state->AddBuiltinCommand("enable_language", cmEnableLanguageCommand);
state->AddBuiltinCommand("enable_testing", cmEnableTestingCommand);
state->AddBuiltinCommand("get_source_file_property",
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index baa1198..6db6767 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -180,35 +180,90 @@
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(config)) {
- auto addLinkedTarget =
- [this, &lang, &config, &dirs, &direct_emitted, &forward_emitted,
- gg](cmGeneratorTarget const* linkee, Forwarding forward) {
- if (linkee &&
- !linkee->IsImported()
- // Skip targets that build after this one in a static lib cycle.
- && gg->TargetOrderIndexLess(linkee, this->GeneratorTarget)
- // We can ignore the INTERFACE_LIBRARY items because
- // Target->GetLinkInformation already processed their
- // link interface and they don't have any output themselves.
- && (linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
- // Synthesized targets may have relevant rules.
- || linkee->IsSynthetic()) &&
- ((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) ||
- (lang == "Fortran"_s && linkee->HaveFortranSources(config)))) {
- cmLocalGenerator* lg = linkee->GetLocalGenerator();
- std::string di = linkee->GetSupportDirectory();
- if (lg->GetGlobalGenerator()->IsMultiConfig()) {
- di = cmStrCat(di, '/', config);
- }
- if (forward == Forwarding::Yes &&
- forward_emitted.insert(linkee).second) {
- dirs.Forward.push_back(di);
- }
- if (direct_emitted.insert(linkee).second) {
- dirs.Direct.emplace_back(di);
+
+ auto findSyntheticTarget =
+ [this,
+ &config](cmGeneratorTarget const* linkee) -> cmGeneratorTarget const* {
+ if (!linkee) {
+ return nullptr;
+ }
+
+ // Check the map of direct synthetic dependencies for a substitute
+ auto const& synthDeps = this->GeneratorTarget->GetSyntheticDeps(config);
+ auto it = synthDeps.find(linkee);
+ if (it != synthDeps.end() && !it->second.empty()) {
+ return it->second.front();
+ }
+
+ // Check linked targets to finding synthetic targets for transitive deps
+ std::vector<cmGeneratorTarget const*> pending;
+ std::set<cmGeneratorTarget const*> visited;
+ for (auto const& dep : synthDeps) {
+ for (auto const* synth : dep.second) {
+ if (synth && visited.insert(synth).second) {
+ pending.push_back(synth);
}
}
- };
+ }
+
+ while (!pending.empty()) {
+ auto const* current = pending.back();
+ pending.pop_back();
+ auto const& transitiveSynthDeps = current->GetSyntheticDeps(config);
+ auto itLinkeeSynth = transitiveSynthDeps.find(linkee);
+ if (itLinkeeSynth != transitiveSynthDeps.end() &&
+ !itLinkeeSynth->second.empty()) {
+ return itLinkeeSynth->second.front();
+ }
+ for (auto const& entry : transitiveSynthDeps) {
+ for (auto const* synth : entry.second) {
+ if (synth && visited.insert(synth).second) {
+ pending.push_back(synth);
+ }
+ }
+ }
+ }
+
+ return nullptr;
+ };
+
+ auto addLinkedTarget = [this, &lang, &config, &dirs, &direct_emitted,
+ &forward_emitted, &findSyntheticTarget,
+ gg](cmGeneratorTarget const* linkee,
+ Forwarding forward) {
+ // Check if the linkee has a synthetic target to use for importing
+ cmGeneratorTarget const* mappedLinkee = linkee;
+ if (auto const* synth = findSyntheticTarget(linkee)) {
+ mappedLinkee = synth;
+ }
+
+ if (mappedLinkee &&
+ !mappedLinkee->IsImported()
+ // Skip targets that build after this one in a static lib cycle.
+ && gg->TargetOrderIndexLess(mappedLinkee, this->GeneratorTarget)
+ // We can ignore the INTERFACE_LIBRARY items because
+ // Target->GetLinkInformation already processed their
+ // link interface and they don't have any output themselves.
+ && (mappedLinkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
+ // Synthesized targets may have relevant rules.
+ || mappedLinkee->IsSynthetic()) &&
+ ((lang == "CXX"_s && mappedLinkee->HaveCxx20ModuleSources()) ||
+ (lang == "Fortran"_s &&
+ mappedLinkee->HaveFortranSources(config)))) {
+ cmLocalGenerator* lg = mappedLinkee->GetLocalGenerator();
+ std::string di = mappedLinkee->GetSupportDirectory();
+ if (lg->GetGlobalGenerator()->IsMultiConfig()) {
+ di = cmStrCat(di, '/', config);
+ }
+ if (forward == Forwarding::Yes &&
+ forward_emitted.insert(mappedLinkee).second) {
+ dirs.Forward.push_back(di);
+ }
+ if (direct_emitted.insert(mappedLinkee).second) {
+ dirs.Direct.emplace_back(di);
+ }
+ }
+ };
for (auto const& item : cli->GetItems()) {
if (item.Target) {
addLinkedTarget(item.Target, Forwarding::No);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 5ff8784..7f41fcf 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -2292,9 +2292,13 @@
}
}
- // Add runtime paths required by the languages to always be
- // present. This is done even when skipping rpath support.
- {
+ // Add runtime paths required by the toolchains' runtime libraries.
+ // This is done even when skipping RPATH entries modeled by CMake.
+ // However, INSTALL_REMOVE_ENVIRONMENT_RPATH tells us to exclude
+ // toolchain-defined RPATH entries from installation.
+ bool const removeEnvironmentRPath = for_install &&
+ this->Target->GetPropertyAsBool("INSTALL_REMOVE_ENVIRONMENT_RPATH");
+ if (!removeEnvironmentRPath) {
cmGeneratorTarget::LinkClosure const* lc =
this->Target->GetLinkClosure(this->Config);
for (std::string const& li : lc->Languages) {
@@ -2310,8 +2314,8 @@
}
}
- // Add runtime paths required by the platform to always be
- // present. This is done even when skipping rpath support.
+ // Add runtime paths required by the platform to always be present.
+ // This is done even when skipping RPATH entries modeled by CMake.
cmCLI_ExpandListUnique(this->RuntimeAlways, runtimeDirs, emitted);
}
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 6befcbf..2309897 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -4,7 +4,6 @@
#include <array>
#include <cstdio>
-#include <cstring>
#include <functional>
#include <set>
#include <sstream>
@@ -25,9 +24,9 @@
#include "cmList.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmRange.h"
+#include "cmScriptGenerator.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -85,7 +84,6 @@
"CMAKE_TRY_COMPILE_OSX_ARCHITECTURES";
std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
"CMAKE_TRY_COMPILE_PLATFORM_VARIABLES";
-std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED";
std::string const kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT =
"CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT";
std::string const kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT =
@@ -738,7 +736,7 @@
std::string langFlags = cmStrCat("CMAKE_", li, "_FLAGS");
cmValue flags = this->Makefile->GetDefinition(langFlags);
fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(),
- cmOutputConverter::EscapeForCMake(*flags).c_str());
+ cmScriptGenerator::Quote(*flags).str().c_str());
fprintf(fout,
"set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
" ${COMPILE_DEFINITIONS}\")\n",
@@ -775,7 +773,7 @@
cmStrCat("CMAKE_", li, "_FLAGS_", cfg);
cmValue flagsCfg = this->Makefile->GetDefinition(langFlagsCfg);
fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(),
- cmOutputConverter::EscapeForCMake(*flagsCfg).c_str());
+ cmScriptGenerator::Quote(*flagsCfg).str().c_str());
if (flagsCfg) {
cmakeVariables.emplace(langFlagsCfg, *flagsCfg);
}
@@ -786,7 +784,7 @@
cmValue exeLinkFlags =
this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
- cmOutputConverter::EscapeForCMake(*exeLinkFlags).c_str());
+ cmScriptGenerator::Quote(*exeLinkFlags).str().c_str());
if (exeLinkFlags) {
cmakeVariables.emplace("CMAKE_EXE_LINKER_FLAGS", *exeLinkFlags);
}
@@ -812,14 +810,14 @@
std::string langLinkFlags = cmStrCat("CMAKE_", li, "_LINK_FLAGS");
cmValue flags = this->Makefile->GetDefinition(langLinkFlags);
fprintf(fout, "set(CMAKE_%s_LINK_FLAGS %s)\n", li.c_str(),
- cmOutputConverter::EscapeForCMake(*flags).c_str());
+ cmScriptGenerator::Quote(*flags).str().c_str());
std::string langLinkFlagsConfig =
cmStrCat("CMAKE_", li, "_LINK_FLAGS_", tcConfig);
cmValue flagsConfig =
this->Makefile->GetDefinition(langLinkFlagsConfig);
fprintf(fout, "set(CMAKE_%s_LINK_FLAGS_%s %s)\n", li.c_str(),
tcConfig.c_str(),
- cmOutputConverter::EscapeForCMake(*flagsConfig).c_str());
+ cmScriptGenerator::Quote(*flagsConfig).str().c_str());
if (flags) {
cmakeVariables.emplace(langLinkFlags, *flags);
@@ -1058,15 +1056,15 @@
}
fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n",
targetName.c_str(),
- cmOutputConverter::EscapeForCMake(p.first).c_str(),
- cmOutputConverter::EscapeForCMake(p.second).c_str());
+ cmScriptGenerator::Quote(p.first).str().c_str(),
+ cmScriptGenerator::Quote(p.second).str().c_str());
}
if (!arguments.LinkOptions.empty()) {
std::vector<std::string> options;
options.reserve(arguments.LinkOptions.size());
for (auto const& option : arguments.LinkOptions) {
- options.emplace_back(cmOutputConverter::EscapeForCMake(option));
+ options.emplace_back(cmScriptGenerator::Quote(option));
}
if (targetType == cmStateEnums::STATIC_LIBRARY) {
@@ -1137,7 +1135,6 @@
vars.insert(kCMAKE_SYSROOT);
vars.insert(kCMAKE_SYSROOT_COMPILE);
vars.insert(kCMAKE_SYSROOT_LINK);
- vars.insert(kCMAKE_WARN_DEPRECATED);
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s);
vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s);
@@ -1368,8 +1365,8 @@
dir.Load(binDir);
std::set<std::string> deletedFiles;
for (unsigned long i = 0; i < dir.GetNumberOfFiles(); ++i) {
- char const* fileName = dir.GetFile(i);
- if (strcmp(fileName, ".") != 0 && strcmp(fileName, "..") != 0 &&
+ std::string const& fileName = dir.GetFileName(i);
+ if (fileName != "." && fileName != ".." &&
// Do not delete NFS temporary files.
!cmHasPrefix(fileName, ".nfs")) {
if (deletedFiles.insert(fileName).second) {
diff --git a/Source/cmCxxModuleMetadata.cxx b/Source/cmCxxModuleMetadata.cxx
index bf3a875..869e4c5 100644
--- a/Source/cmCxxModuleMetadata.cxx
+++ b/Source/cmCxxModuleMetadata.cxx
@@ -16,6 +16,7 @@
#include "cmsys/FStream.hxx"
#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratedFileStream.h"
#include "cmJSONState.h"
#include "cmListFileCache.h"
@@ -504,8 +505,10 @@
void PopulateFileSet(cmTarget& target, MetaDataProperties const& props)
{
- auto fileSet = target.GetOrCreateFileSet("CXX_MODULES", "CXX_MODULES",
- cmFileSetVisibility::Public);
+ auto fileSet =
+ target.GetOrCreateFileSet(std::string{ cm::FileSetMetadata::CXX_MODULES },
+ std::string{ cm::FileSetMetadata::CXX_MODULES },
+ cm::FileSetMetadata::Visibility::Public);
for (auto const& source : props.Sources) {
fileSet.first->AddFileEntry(source);
diff --git a/Source/cmCxxModuleUsageEffects.cxx b/Source/cmCxxModuleUsageEffects.cxx
index aa1a13f..8985a58 100644
--- a/Source/cmCxxModuleUsageEffects.cxx
+++ b/Source/cmCxxModuleUsageEffects.cxx
@@ -2,17 +2,28 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmCxxModuleUsageEffects.h"
-cmCxxModuleUsageEffects::cmCxxModuleUsageEffects(
- cmGeneratorTarget const* /*gt*/)
- : Hash("0000000000000000000000000000000000000000")
+#include <cm/optional>
+
+#include "cmCryptoHash.h"
+#include "cmGeneratorTarget.h"
+#include "cmTarget.h"
+
+cmCxxModuleUsageEffects::cmCxxModuleUsageEffects(cmGeneratorTarget const* gt)
{
- // TODO: collect information from the generator target as to what might
- // affect module consumption.
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
+ this->Hash = hasher.HashString(gt->GetName());
+
+ // Collect compile features from the consuming target.
+ for (auto const& feature : gt->Target->GetCompileFeaturesEntries()) {
+ this->CompileFeatures.emplace_back(feature);
+ }
}
-void cmCxxModuleUsageEffects::ApplyToTarget(cmTarget* /*tgt*/)
+void cmCxxModuleUsageEffects::ApplyToTarget(cmTarget* tgt)
{
- // TODO: apply the information collected in the constructor
+ for (auto const& feature : this->CompileFeatures) {
+ tgt->AppendProperty("COMPILE_FEATURES", feature.Value, feature.Backtrace);
+ }
}
std::string const& cmCxxModuleUsageEffects::GetHash() const
diff --git a/Source/cmDebuggerAdapter.cxx b/Source/cmDebuggerAdapter.cxx
index 7cf9efe..7dfb334 100644
--- a/Source/cmDebuggerAdapter.cxx
+++ b/Source/cmDebuggerAdapter.cxx
@@ -312,6 +312,14 @@
while (SessionActive.load()) {
if (auto payload = Session->getPayload()) {
payload();
+ } else {
+ // Connection closed or unrecoverable error.
+ BreakpointManager->ClearAll();
+ ExceptionManager->ClearAll();
+ ClearStepRequests();
+ ContinueSem->Notify();
+ DisconnectEvent->Fire();
+ SessionActive.store(false);
}
}
});
diff --git a/Source/cmDebuggerPosixPipeConnection.cxx b/Source/cmDebuggerPosixPipeConnection.cxx
index ac5fd04..e4572fa 100644
--- a/Source/cmDebuggerPosixPipeConnection.cxx
+++ b/Source/cmDebuggerPosixPipeConnection.cxx
@@ -10,6 +10,7 @@
#include <unistd.h>
#include <sys/socket.h>
+#include <sys/types.h>
namespace cmDebugger {
@@ -110,10 +111,13 @@
{
size_t result = 0;
if (rw_pipe >= 0) {
- result = ::read(rw_pipe, buffer, n);
- if (result == 0) {
+ ssize_t count = ::read(rw_pipe, buffer, n);
+ if (count <= 0) {
+ // EOF or error (including EBADF from a concurrent close).
close();
+ return 0;
}
+ result = static_cast<size_t>(count);
}
return result;
@@ -174,17 +178,26 @@
}
}
+void cmDebuggerPipeClient_POSIX::ShutdownForTesting()
+{
+ if (isOpen()) {
+ ::shutdown(rw_pipe, SHUT_RDWR);
+ }
+}
+
size_t cmDebuggerPipeClient_POSIX::read(void* buffer, size_t n)
{
- int count = 0;
+ ssize_t count = 0;
if (isOpen()) {
- count = static_cast<int>(::read(rw_pipe, buffer, n));
- if (count == 0) {
+ count = ::read(rw_pipe, buffer, n);
+ if (count <= 0) {
+ // EOF or error (including EBADF from a concurrent close).
close();
+ return 0;
}
}
- return count;
+ return static_cast<size_t>(count);
}
bool cmDebuggerPipeClient_POSIX::write(void const* buffer, size_t n)
diff --git a/Source/cmDebuggerPosixPipeConnection.h b/Source/cmDebuggerPosixPipeConnection.h
index 98e3f6f..d1e09d6 100644
--- a/Source/cmDebuggerPosixPipeConnection.h
+++ b/Source/cmDebuggerPosixPipeConnection.h
@@ -69,6 +69,11 @@
size_t read(void* buffer, size_t n) override;
bool write(void const* buffer, size_t n) override;
+ // Unit-test helper: signal EOF on both halves of the socket without
+ // freeing the fd, so a sibling thread blocked in read() wakes up
+ // cleanly. Production code does not use cmDebuggerPipeClient.
+ void ShutdownForTesting();
+
private:
std::string const PipeName;
int rw_pipe = -1;
diff --git a/Source/cmDebuggerVariablesHelper.cxx b/Source/cmDebuggerVariablesHelper.cxx
index 07d9802..9f8338f 100644
--- a/Source/cmDebuggerVariablesHelper.cxx
+++ b/Source/cmDebuggerVariablesHelper.cxx
@@ -16,6 +16,7 @@
#include "cmDebuggerStackFrame.h"
#include "cmDebuggerVariables.h"
#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmListFileCache.h"
@@ -195,18 +196,19 @@
return {};
}
- static auto visibilityString = [](cmFileSetVisibility visibility) {
- switch (visibility) {
- case cmFileSetVisibility::Private:
- return "Private";
- case cmFileSetVisibility::Public:
- return "Public";
- case cmFileSetVisibility::Interface:
- return "Interface";
- default:
- return "Unknown";
- }
- };
+ static auto visibilityString =
+ [](cm::FileSetMetadata::Visibility visibility) {
+ switch (visibility) {
+ case cm::FileSetMetadata::Visibility::Private:
+ return "Private";
+ case cm::FileSetMetadata::Visibility::Public:
+ return "Public";
+ case cm::FileSetMetadata::Visibility::Interface:
+ return "Interface";
+ default:
+ return "Unknown";
+ }
+ };
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
@@ -305,15 +307,15 @@
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "CompileOptions", supportsVariableType,
target->GetCompileOptionsEntries()));
- targetVariables->AddSubVariables(
- CreateIfAny(variablesManager, "CxxModuleSets", supportsVariableType,
- target->GetCxxModuleSetsEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "CxxModuleSets", supportsVariableType,
+ target->GetFileSetsEntries(cm::FileSetMetadata::CXX_MODULES)));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "HeaderSets", supportsVariableType,
- target->GetHeaderSetsEntries()));
+ target->GetFileSetsEntries(cm::FileSetMetadata::HEADERS)));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "InterfaceHeaderSets", supportsVariableType,
- target->GetInterfaceHeaderSetsEntries()));
+ target->GetInterfaceFileSetsEntries(cm::FileSetMetadata::HEADERS)));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "LinkDirectories", supportsVariableType,
target->GetLinkDirectoriesEntries()));
diff --git a/Source/cmDebuggerWindowsPipeConnection.h b/Source/cmDebuggerWindowsPipeConnection.h
index 5611255..dad23fb 100644
--- a/Source/cmDebuggerWindowsPipeConnection.h
+++ b/Source/cmDebuggerWindowsPipeConnection.h
@@ -89,6 +89,11 @@
size_t read(void* buffer, size_t n) override;
bool write(void const* buffer, size_t n) override;
+ // Unit-test helper: on Windows CloseHandle already cancels any
+ // pending overlapped I/O, so this just delegates to close().
+ // Production code does not use cmDebuggerPipeClient.
+ void ShutdownForTesting() { this->close(); }
+
private:
std::string GetErrorMessage(DWORD errorCode);
diff --git a/Source/cmDiagnostics.cxx b/Source/cmDiagnostics.cxx
new file mode 100644
index 0000000..60d3ec4
--- /dev/null
+++ b/Source/cmDiagnostics.cxx
@@ -0,0 +1,98 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmDiagnostics.h"
+
+#include <cassert>
+#include <map>
+#include <string>
+#include <utility>
+
+#include <cmext/string_view>
+
+#include "cmStringAlgorithms.h"
+
+namespace {
+cm::optional<cmDiagnosticCategory> stringToCategory(cm::string_view input)
+{
+ using Map = std::map<cm::string_view, cmDiagnosticCategory>;
+ static Map const mapping = {
+#define CATEGORY_MAP(C) { #C ""_s, cmDiagnostics::C },
+ CM_FOR_EACH_DIAGNOSTIC_CATEGORY(CATEGORY_MAP)
+#undef CATEGORY_MAP
+ };
+
+ assert(!input.empty());
+ if (input.size() >= 4 && cmHasLiteralPrefix(input, "CMD_")) {
+ auto const i = mapping.find(input);
+ if (i != mapping.end()) {
+ return i->second;
+ }
+ }
+
+ return cm::nullopt;
+}
+}
+
+#if __cplusplus < 201703L
+// Prior to C++17, the compiler is unhappy if this member doesn't have explicit
+// storage... and clang-tidy is unhappy if it does.
+// NOLINTNEXTLINE(*-redundant-declaration)
+constexpr cmDiagnostics::DiagnosticCategoryInformation
+ cmDiagnostics::CategoryInfo[cmDiagnostics::CategoryCount];
+#endif
+
+cm::string_view cmDiagnostics::GetActionString(DiagnosticAction action)
+{
+ switch (action) {
+ case Ignore:
+ return "IGNORE"_s;
+ case Warn:
+ return "WARN"_s;
+ case SendError:
+ return "SEND_ERROR"_s;
+ case FatalError:
+ return "FATAL_ERROR"_s;
+ default:
+ return {};
+ }
+}
+
+cm::string_view cmDiagnostics::GetCategoryString(DiagnosticCategory category)
+{
+ static cm::string_view const names[CategoryCount] = {
+ {}, // CMD_NONE
+#define CATEGORY_NAME(C) #C ""_s,
+ CM_FOR_EACH_DIAGNOSTIC_CATEGORY(CATEGORY_NAME)
+#undef CATEGORY_MAP
+ };
+
+ if (category < CategoryCount) {
+ return names[category];
+ }
+ return {};
+}
+
+cm::optional<cmDiagnosticAction> cmDiagnostics::GetDiagnosticAction(
+ cm::string_view name)
+{
+ if (name == "IGNORE"_s) {
+ return DiagnosticAction::Ignore;
+ }
+ if (name == "WARN"_s) {
+ return DiagnosticAction::Warn;
+ }
+ if (name == "SEND_ERROR"_s) {
+ return DiagnosticAction::SendError;
+ }
+ if (name == "FATAL_ERROR"_s) {
+ return DiagnosticAction::FatalError;
+ }
+
+ return cm::nullopt;
+}
+
+cm::optional<cmDiagnosticCategory> cmDiagnostics::GetDiagnosticCategory(
+ cm::string_view name)
+{
+ return stringToCategory(name);
+}
diff --git a/Source/cmDiagnostics.h b/Source/cmDiagnostics.h
new file mode 100644
index 0000000..1d06382
--- /dev/null
+++ b/Source/cmDiagnostics.h
@@ -0,0 +1,104 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+
+#include <cm/optional>
+#include <cm/string_view>
+
+// https://github.com/include-what-you-use/include-what-you-use/issues/1934
+// IWYU pragma: no_forward_declare cmDiagnostics::DiagnosticAction
+// IWYU pragma: no_forward_declare cmDiagnostics::DiagnosticCategory
+
+// The list of diagnostic categories along with their associated data.
+// Each entry is of the form `SELECT(ACTION, <default>, <parent>, <name>)`.
+// Entries MUST appear in the order that a depth-first enumeration would
+// produce.
+//
+// When this changes, Help/manual/presets/schema.json must also be updated.
+
+#define CM_FOR_EACH_DIAGNOSTIC_TABLE(ACTION, SELECT) \
+ SELECT(ACTION, Warn, CMD_NONE, CMD_AUTHOR, 12) \
+ SELECT(ACTION, Warn, CMD_AUTHOR, CMD_DEPRECATED, 1) \
+ SELECT(ACTION, Ignore, CMD_NONE, CMD_UNINITIALIZED, 1) \
+ SELECT(ACTION, Warn, CMD_NONE, CMD_UNUSED_CLI, 1)
+
+#define CM_SELECT_CATEGORY(F, D, P, C, V) F(C)
+#define CM_FOR_EACH_DIAGNOSTIC_CATEGORY(ACTION) \
+ CM_FOR_EACH_DIAGNOSTIC_TABLE(ACTION, CM_SELECT_CATEGORY)
+
+/** \class cmDiagnostic
+ * \brief Handles CMake diagnostic (warning) behavior
+ *
+ * See the cmake-diagnostics(7) manual for an overview of this class's purpose.
+ */
+class cmDiagnostics
+{
+public:
+ /// Action to take when a diagnostic is triggered
+ enum DiagnosticAction : std::uint8_t
+ {
+ Undefined = 0,
+ Ignore,
+ Warn,
+ SendError,
+ FatalError,
+ };
+
+ /// Diagnostic category identifiers
+ enum DiagnosticCategory : unsigned
+ {
+ CMD_NONE,
+#define DIAGNOSTIC_ENUM(CATEGORY) CATEGORY,
+ CM_FOR_EACH_DIAGNOSTIC_CATEGORY(DIAGNOSTIC_ENUM)
+#undef DIAGNOSTIC_ENUM
+
+ /** \brief Always the last entry.
+ *
+ * Used to determine the number of diagnostic categories. Also useful to
+ * avoid adding a comma the last diagnostic category when adding a new one.
+ */
+ CMD_COUNT
+ };
+ constexpr static size_t CategoryCount = static_cast<size_t>(CMD_COUNT);
+
+ struct DiagnosticCategoryInformation
+ {
+ DiagnosticCategory Parent;
+ DiagnosticAction DefaultAction;
+ int PresetVersion;
+ };
+
+ constexpr static DiagnosticCategoryInformation
+ CategoryInfo[CategoryCount] = {
+ { CMD_NONE, Undefined, 0 }, // CMD_NONE
+#define DIAGNOSTIC_CATEGORY_INFO(F, D, P, C, V) { P, D, V },
+ CM_FOR_EACH_DIAGNOSTIC_TABLE(UNUSED, DIAGNOSTIC_CATEGORY_INFO)
+#undef DIAGNOSTIC_CATEGORY_INFO
+ };
+
+ //! convert an action identifier into a string
+ static cm::string_view GetActionString(DiagnosticAction);
+
+ //! convert a category identifier into a string
+ static cm::string_view GetCategoryString(DiagnosticCategory);
+
+ //! Convert a string action into an identifier
+ static cm::optional<DiagnosticAction> GetDiagnosticAction(
+ cm::string_view name);
+
+ //! Convert a string category into an identifier
+ static cm::optional<DiagnosticCategory> GetDiagnosticCategory(
+ cm::string_view name);
+
+ /** Represent a set of diagnostic category actions. */
+ using DiagnosticMap = std::array<DiagnosticAction, CategoryCount>;
+};
+
+using cmDiagnosticCategory = cmDiagnostics::DiagnosticCategory;
+using cmDiagnosticAction = cmDiagnostics::DiagnosticAction;
diff --git a/Source/cmDiscoverTestsCommand.cxx b/Source/cmDiscoverTestsCommand.cxx
new file mode 100644
index 0000000..278a032
--- /dev/null
+++ b/Source/cmDiscoverTestsCommand.cxx
@@ -0,0 +1,117 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmDiscoverTestsCommand.h"
+
+#include <cstddef>
+#include <ostream>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cmext/string_view>
+
+#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
+#include "cmExecutionStatus.h"
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmScriptGenerator.h"
+#include "cmTestDiscovery.h"
+#include "cmTestGenerator.h"
+
+namespace {
+
+struct Arguments : cmTestDiscoveryArgs
+{
+ bool CommandExpandLists = false;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Configurations;
+};
+
+class DiscoveryGenerator : public cmTestGenerator
+{
+public:
+ DiscoveryGenerator(Arguments arguments, cmListFileBacktrace backtrace)
+ : cmTestGenerator(nullptr, arguments.Configurations)
+ , Args{ std::move(arguments) }
+ , Backtrace{ std::move(backtrace) }
+ {
+ }
+
+private:
+ void GenerateProperties(std::ostream& os, Indent indent,
+ std::vector<std::string> const& props,
+ std::string const& config, cmGeneratorExpression& ge)
+ {
+ for (std::size_t i = 0; i < props.size(); i += 2) {
+ os << '\n'
+ << indent << Quote(props[i]) << ' '
+ << Quote(ge.Parse(props[i + 1])->Evaluate(this->LG, config));
+ }
+ }
+
+ void GenerateScriptForConfig(std::ostream& os, std::string const& config,
+ Indent indent) override
+ {
+ // Set up generator expression evaluation context.
+ cmGeneratorExpression ge(*this->LG->GetMakefile()->GetCMakeInstance(),
+ this->Backtrace);
+
+ auto const in = indent.Next();
+ os << indent << "discover_tests(COMMAND ";
+ this->GenerateCommand(os, this->Args.Command, config,
+ this->Args.CommandExpandLists, ge);
+ os << '\n' << in << "DISCOVERY_ARGS";
+ for (auto const& arg : this->Args.DiscoveryArgs) {
+ os << ' ' << Quote(arg);
+ }
+ os << '\n' << in << "DISCOVERY_MATCH " << Quote(this->Args.DiscoveryMatch);
+ if (!this->Args.DiscoveryProperties.empty()) {
+ os << '\n' << in << "DISCOVERY_PROPERTIES";
+ this->GenerateProperties(os, in.Next(), this->Args.DiscoveryProperties,
+ config, ge);
+ }
+ os << '\n' << in << "TEST_NAME " << Quote(this->Args.TestName);
+ os << '\n' << in << "TEST_ARGS";
+ for (auto const& arg : this->Args.TestArgs) {
+ os << ' ' << Quote(arg);
+ }
+ os << '\n' << in << "TEST_PROPERTIES";
+ this->GenerateProperties(os, in.Next(), this->Args.TestProperties, config,
+ ge);
+ os << '\n' << in.Next();
+ this->GenerateBacktrace(os, this->Backtrace);
+ os << '\n' << in << ")\n";
+ }
+
+ Arguments Args;
+ cmListFileBacktrace Backtrace;
+};
+
+} // namespace
+
+bool cmDiscoverTestsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ static auto const parser =
+ cmArgumentParser<Arguments>{ cmTestDiscoveryParser<Arguments>() }
+ .Bind("COMMAND_EXPAND_LISTS"_s, &Arguments::CommandExpandLists)
+ .Bind("CONFIGURATIONS"_s, &Arguments::Configurations);
+
+ auto unparsed = std::vector<std::string>{};
+ Arguments arguments = parser.Parse(args, &unparsed);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
+
+ if (!unparsed.empty()) {
+ status.SetError(" given unknown argument \"" + unparsed.front() + "\".");
+ return false;
+ }
+
+ cmMakefile& mf = status.GetMakefile();
+ mf.AddTestGenerator(cm::make_unique<DiscoveryGenerator>(std::move(arguments),
+ mf.GetBacktrace()));
+ return true;
+}
diff --git a/Source/cmDiscoverTestsCommand.h b/Source/cmDiscoverTestsCommand.h
new file mode 100644
index 0000000..a41345a
--- /dev/null
+++ b/Source/cmDiscoverTestsCommand.h
@@ -0,0 +1,13 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmDiscoverTestsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
diff --git a/Source/cmDyndepCollation.cxx b/Source/cmDyndepCollation.cxx
index 2a17925..24e43d1 100644
--- a/Source/cmDyndepCollation.cxx
+++ b/Source/cmDyndepCollation.cxx
@@ -20,10 +20,11 @@
#include "cmCxxModuleMetadata.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExportSet.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h" // IWYU pragma: keep
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCxxModuleBmiGenerator.h"
@@ -56,7 +57,6 @@
cm::GenEx::Context const context(gt->LocalGenerator, config);
TdiSourceInfo info;
cmTarget const* tgt = gt->Target;
- auto all_file_sets = tgt->GetAllFileSetNames();
Json::Value& tdi_sources = info.Sources = Json::objectValue;
Json::Value& tdi_cxx_module_info = info.CxxModules = Json::objectValue;
@@ -93,32 +93,20 @@
}
}
- for (auto const& file_set_name : all_file_sets) {
- auto const* file_set = tgt->GetFileSet(file_set_name);
- if (!file_set) {
- gt->Makefile->IssueMessage(MessageType::INTERNAL_ERROR,
- cmStrCat("Target \"", tgt->GetName(),
- "\" is tracked to have file set \"",
- file_set_name,
- "\", but it was not found."));
- continue;
- }
+ for (auto const* file_set : gt->GetAllFileSets()) {
auto fs_type = file_set->GetType();
// We only care about C++ module sources here.
- if (fs_type != "CXX_MODULES"_s) {
+ if (fs_type != cm::FileSetMetadata::CXX_MODULES) {
+ continue;
+ }
+ // Synthetic (BMI-only) targets do not build private C++ modules.
+ if (tgt->IsSynthetic() &&
+ file_set->GetVisibility() ==
+ cm::FileSetMetadata::Visibility::Private) {
continue;
}
- auto fileEntries = file_set->CompileFileEntries();
- auto directoryEntries = file_set->CompileDirectoryEntries();
-
- auto directories =
- file_set->EvaluateDirectoryEntries(directoryEntries, context, gt);
- std::map<std::string, std::vector<std::string>> files_per_dirs;
- for (auto const& entry : fileEntries) {
- file_set->EvaluateFileEntry(directories, files_per_dirs, entry, context,
- gt);
- }
+ auto files_per_dirs = file_set->GetFiles(context, gt);
Json::Value fs_dest = Json::nullValue;
for (auto const& ig : gt->Makefile->GetInstallGenerators()) {
@@ -131,32 +119,20 @@
}
}
- // Detect duplicate sources.
- std::set<std::string> visited_sources;
-
- for (auto const& files_per_dir : files_per_dirs) {
+ for (auto const& files_per_dir : files_per_dirs.first) {
for (auto const& file : files_per_dir.second) {
auto const full_file = cmSystemTools::CollapseFullPath(file);
auto lookup = sf_map.find(full_file);
if (lookup == sf_map.end()) {
- if (visited_sources.count(full_file)) {
- // Duplicate source; raise an author warning.
- gt->Makefile->IssueMessage(
- MessageType::AUTHOR_WARNING,
- cmStrCat(
- "Target \"", tgt->GetName(), "\" has source file\n ", file,
- "\nin a \"FILE_SET TYPE CXX_MODULES\" multiple times."));
- continue;
- }
- gt->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Target \"", tgt->GetName(), "\" has source file\n ",
- file,
- "\nin a \"FILE_SET TYPE CXX_MODULES\" but it is not "
- "scheduled for compilation."));
+ gt->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" has source file\n ", file,
+ "\nin a \"FILE_SET TYPE ",
+ cm::FileSetMetadata::CXX_MODULES,
+ "\" but it is not "
+ "scheduled for compilation."));
continue;
}
- visited_sources.insert(full_file);
auto const* sf = lookup->second.first;
CompileType const ct = lookup->second.second;
@@ -206,8 +182,8 @@
tdi_module_info["relative-directory"] = files_per_dir.first;
tdi_module_info["name"] = file_set->GetName();
tdi_module_info["type"] = file_set->GetType();
- tdi_module_info["visibility"] =
- std::string(cmFileSetVisibilityToName(file_set->GetVisibility()));
+ tdi_module_info["visibility"] = std::string(
+ cm::FileSetMetadata::VisibilityToName(file_set->GetVisibility()));
tdi_module_info["destination"] = fs_dest;
}
}
@@ -398,7 +374,8 @@
std::string RelativeDirectory;
std::string SourcePath;
std::string Type;
- cmFileSetVisibility Visibility = cmFileSetVisibility::Private;
+ cm::FileSetMetadata::Visibility Visibility =
+ cm::FileSetMetadata::Visibility::Private;
cm::optional<std::string> Destination;
std::vector<std::string> IncludeDirectories;
std::vector<std::string> Definitions;
@@ -521,7 +498,7 @@
}
fsi.SourcePath = tdi_cxx_module_info["source"].asString();
fsi.Type = tdi_cxx_module_info["type"].asString();
- fsi.Visibility = cmFileSetVisibilityFromName(
+ fsi.Visibility = cm::FileSetMetadata::VisibilityFromName(
tdi_cxx_module_info["visibility"].asString(), nullptr);
auto const& tdi_fs_dest = tdi_cxx_module_info["destination"];
if (tdi_fs_dest.isString()) {
@@ -671,8 +648,8 @@
cmSystemTools::Error(
cmStrCat("Output ", object.PrimaryOutput, " provides the `",
provides.LogicalName,
- "` module but it is not found in a `FILE_SET` of type "
- "`CXX_MODULES`"));
+ "` module but it is not found in a `FILE_SET` of type `",
+ cm::FileSetMetadata::CXX_MODULES, '`'));
result = false;
}
@@ -712,12 +689,13 @@
}
// Verify the fileset type for the object.
- if (file_set.Type == "CXX_MODULES"_s) {
+ if (file_set.Type == cm::FileSetMetadata::CXX_MODULES) {
if (!has_provides) {
- cmSystemTools::Error(
- cmStrCat("Output ", object.PrimaryOutput,
- " is of type `CXX_MODULES` but does not provide a module "
- "interface unit or partition"));
+ cmSystemTools::Error(cmStrCat("Output ", object.PrimaryOutput,
+ " is of type `",
+ cm::FileSetMetadata::CXX_MODULES,
+ "` but does not provide a module "
+ "interface unit or partition"));
result = false;
continue;
}
@@ -726,10 +704,11 @@
} else {
if (has_provides) {
auto const& provides = object.Provides[0];
- cmSystemTools::Error(cmStrCat(
- "Source ", file_set.SourcePath, " provides the `",
- provides.LogicalName, "` C++ module but is of type `", file_set.Type,
- "` module but must be of type `CXX_MODULES`"));
+ cmSystemTools::Error(
+ cmStrCat("Source ", file_set.SourcePath, " provides the `",
+ provides.LogicalName, "` C++ module but is of type `",
+ file_set.Type, "` module but must be of type `",
+ cm::FileSetMetadata::CXX_MODULES, '`'));
result = false;
}
@@ -737,7 +716,7 @@
continue;
}
- if (!cmFileSetVisibilityIsForInterface(file_set.Visibility)) {
+ if (!cm::FileSetMetadata::VisibilityIsForInterface(file_set.Visibility)) {
// Nothing needs to be conveyed about non-`PUBLIC` modules.
for (auto const& p : object.Provides) {
private_modules.insert(p.LogicalName);
@@ -921,7 +900,7 @@
return false;
}
auto const& file_set = fileset_info_itr->second;
- return !cmFileSetVisibilityIsForInterface(file_set.Visibility);
+ return !cm::FileSetMetadata::VisibilityIsForInterface(file_set.Visibility);
}
bool cmDyndepCollation::IsBmiOnly(cmCxxModuleExportInfo const& exportInfo,
diff --git a/Source/cmEnvironment.cxx b/Source/cmEnvironment.cxx
new file mode 100644
index 0000000..af5a47c
--- /dev/null
+++ b/Source/cmEnvironment.cxx
@@ -0,0 +1,229 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmEnvironment.h"
+
+#include <set>
+#include <sstream>
+#include <utility>
+
+#include <cm/string_view>
+#include <cm/vector>
+#include <cmext/algorithm>
+
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+#if defined(_WIN32)
+# include "cmsys/String.h"
+#endif
+
+bool cmEnvironment::EnvNameLess::operator()(std::string const& lhs,
+ std::string const& rhs) const
+{
+#if defined(_WIN32)
+ // Environment variable names are case-insensitive on Windows
+ return cmsysString_strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
+#else
+ return lhs < rhs;
+#endif
+}
+
+cmEnvironment::cmEnvironment(std::vector<std::string> const& env)
+{
+ for (std::string const& var : env) {
+ this->PutEnv(var);
+ }
+}
+
+void cmEnvironment::PutEnv(std::string const& env)
+{
+ auto const pos = env.find('=');
+ if (pos != std::string::npos) {
+ this->Map[env.substr(0, pos)] = env.substr(pos + 1);
+ } else {
+ this->Map[env] = cm::nullopt;
+ }
+}
+
+void cmEnvironment::UnPutEnv(std::string const& env)
+{
+ this->Map[env] = cm::nullopt;
+}
+
+void cmEnvironment::Update(cmEnvironment&& other)
+{
+ for (auto& kv : other.Map) {
+ this->Map[kv.first] = std::move(kv.second);
+ }
+ other.Map.clear();
+}
+
+std::vector<std::string> cmEnvironment::GetVariables() const
+{
+ auto result = std::vector<std::string>{};
+ result.reserve(this->Map.size());
+ for (auto const& elem : this->Map) {
+ if (elem.second) {
+ result.push_back(elem.first + '=' + *elem.second);
+ }
+ }
+ return result;
+}
+
+std::string cmEnvironment::RecordDifference(
+ cmEnvironment const& original) const
+{
+ cm::string_view nl;
+ std::ostringstream os;
+ for (auto const& elem : this->Map) {
+ if (!elem.second) {
+ // Signify that this variable is being actively unset
+ os << nl << '#' << elem.first << '=';
+ nl = "\n";
+ continue;
+ }
+ auto const it = original.Map.find(elem.first);
+ if (it != original.Map.end() && *elem.second == it->second) {
+ // Skip variables that are unchanged
+ continue;
+ }
+ os << nl << elem.first << '=' << *elem.second;
+ nl = "\n";
+ }
+ return os.str();
+}
+
+namespace {
+
+auto const ValidOperators = std::set<cm::string_view>{
+ "set",
+ "unset",
+ "string_append",
+ "string_prepend",
+ "path_list_append",
+ "path_list_prepend",
+ "cmake_list_append",
+ "cmake_list_prepend",
+};
+
+struct ListAppend
+{
+public:
+ ListAppend(std::string val, char sep)
+ : value(std::move(val))
+ , separator(sep)
+ {
+ }
+
+ void operator()(std::string& output) const
+ {
+ if (!output.empty()) {
+ output += separator;
+ }
+ output += value;
+ }
+
+private:
+ std::string value;
+ char separator;
+};
+
+struct ListPrepend
+{
+public:
+ ListPrepend(std::string val, char sep)
+ : value(std::move(val))
+ , separator(sep)
+ {
+ }
+
+ void operator()(std::string& output) const
+ {
+ if (!output.empty()) {
+ output.insert(output.begin(), separator);
+ }
+ output.insert(0, value);
+ }
+
+private:
+ std::string value;
+ char separator;
+};
+
+} // namespace
+
+bool cmEnvironmentModification::Add(std::vector<std::string> const& envmod)
+{
+ bool ok = true;
+ for (auto const& entry : envmod) {
+ ok &= this->Add(entry);
+ }
+ return ok;
+}
+
+bool cmEnvironmentModification::Add(std::string const& envmod)
+{
+ // Split on `=`
+ auto const eq_loc = envmod.find_first_of('=');
+ if (eq_loc == std::string::npos) {
+ cmSystemTools::Error(cmStrCat(
+ "Error: Missing `=` after the variable name in: ", envmod, '\n'));
+ return false;
+ }
+
+ // Split operation on `:`
+ auto const op_value_start = eq_loc + 1;
+ auto const colon_loc = envmod.find_first_of(':', op_value_start);
+ if (colon_loc == std::string::npos) {
+ cmSystemTools::Error(
+ cmStrCat("Error: Missing `:` after the operation in: ", envmod, '\n'));
+ return false;
+ }
+
+ auto entry = Entry{};
+ entry.Name = envmod.substr(0, eq_loc);
+ entry.Op = envmod.substr(op_value_start, colon_loc - op_value_start);
+ entry.Value = envmod.substr(colon_loc + 1);
+
+ if (entry.Op == "reset") {
+ cm::erase_if(this->Entries,
+ [&entry](Entry const& e) { return e.Name == entry.Name; });
+ return true;
+ }
+
+ if (!cm::contains(ValidOperators, entry.Op)) {
+ cmSystemTools::Error(cmStrCat(
+ "Error: Unrecognized environment manipulation argument: ", entry.Op,
+ '\n'));
+ return false;
+ }
+
+ this->Entries.push_back(std::move(entry));
+ return true;
+}
+
+void cmEnvironmentModification::ApplyTo(cmEnvironment& env)
+{
+ char const path_sep = cmSystemTools::GetSystemPathlistSeparator();
+
+ for (auto const& e : this->Entries) {
+ if (e.Op == "set") {
+ env.PutEnv(e.Name + "=" + e.Value);
+ } else if (e.Op == "unset") {
+ env.UnPutEnv(e.Name);
+ } else if (e.Op == "string_append") {
+ env.Modify(e.Name, [&e](std::string& output) { output += e.Value; });
+ } else if (e.Op == "string_prepend") {
+ env.Modify(e.Name,
+ [&e](std::string& output) { output.insert(0, e.Value); });
+ } else if (e.Op == "path_list_append") {
+ env.Modify(e.Name, ListAppend(e.Value, path_sep));
+ } else if (e.Op == "path_list_prepend") {
+ env.Modify(e.Name, ListPrepend(e.Value, path_sep));
+ } else if (e.Op == "cmake_list_append") {
+ env.Modify(e.Name, ListAppend(e.Value, ';'));
+ } else if (e.Op == "cmake_list_prepend") {
+ env.Modify(e.Name, ListPrepend(e.Value, ';'));
+ }
+ }
+}
diff --git a/Source/cmEnvironment.h b/Source/cmEnvironment.h
new file mode 100644
index 0000000..806015f
--- /dev/null
+++ b/Source/cmEnvironment.h
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+
+/**
+ * Helper class to represent an environment.
+ */
+class cmEnvironment
+{
+public:
+ /** Initialize from `NAME=VALUE` strings. */
+ cmEnvironment(std::vector<std::string> const& env = {});
+
+ /**
+ * Add a single variable (or remove if no = sign) to the current
+ * environment.
+ */
+ void PutEnv(std::string const& env);
+
+ /** Remove a single variable from the current environment. */
+ void UnPutEnv(std::string const& env);
+
+ /**
+ * Move the environment entries from `other` into this one, overwriting
+ * existing variables when a key is already present. */
+ void Update(cmEnvironment&& other);
+
+ /** Modify the value of a variable in-place using a transform function. */
+ template <typename F>
+ void Modify(std::string const& name, F&& transform)
+ {
+ cm::optional<std::string>& val = this->Map[name];
+ if (!val.has_value()) {
+ val = std::string{};
+ }
+ transform(*val);
+ }
+
+ std::vector<std::string> GetVariables() const;
+
+ std::string RecordDifference(cmEnvironment const& original) const;
+
+protected:
+ struct EnvNameLess
+ {
+ bool operator()(std::string const& lhs, std::string const& rhs) const;
+ };
+ std::map<std::string, cm::optional<std::string>, EnvNameLess> Map;
+};
+
+class cmEnvironmentModification
+{
+public:
+ bool Add(std::string const& envmod);
+ bool Add(std::vector<std::string> const& envmod);
+
+ void ApplyTo(cmEnvironment& env);
+
+private:
+ struct Entry
+ {
+ std::string Name;
+ std::string Value;
+ std::string Op;
+ };
+
+ std::vector<Entry> Entries;
+};
diff --git a/Source/cmEvaluatedTargetProperty.cxx b/Source/cmEvaluatedTargetProperty.cxx
index f786985..28b3faf 100644
--- a/Source/cmEvaluatedTargetProperty.cxx
+++ b/Source/cmEvaluatedTargetProperty.cxx
@@ -7,12 +7,15 @@
#include "cmGenExContext.h"
#include "cmGenExEvaluation.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmList.h"
+#include "cmTargetPropertyEntry.h"
struct cmGeneratorExpressionDAGChecker;
+namespace cm {
EvaluatedTargetPropertyEntry::EvaluatedTargetPropertyEntry(
cmLinkItem const& item, cmListFileBacktrace bt)
: LinkItem(item)
@@ -22,8 +25,7 @@
EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
cmGeneratorTarget const* thisTarget, cm::GenEx::Context const& context,
- cmGeneratorExpressionDAGChecker* dagChecker,
- cmGeneratorTarget::TargetPropertyEntry& entry)
+ cmGeneratorExpressionDAGChecker* dagChecker, cm::TargetPropertyEntry& entry)
{
EvaluatedTargetPropertyEntry ee(entry.LinkItem, entry.GetBacktrace());
cmExpandList(entry.Evaluate(context, thisTarget, dagChecker), ee.Values);
@@ -36,8 +38,7 @@
EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
cmGeneratorTarget const* thisTarget, cm::GenEx::Context const& context,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
- in)
+ std::vector<std::unique_ptr<cm::TargetPropertyEntry>> const& in)
{
EvaluatedTargetPropertyEntries out;
out.Entries.reserve(in.size());
@@ -73,6 +74,31 @@
}
}
}
+
+void addInterfaceFileSetsEntry(cmGeneratorTarget const* headTarget,
+ cm::string_view type, std::string const& prop,
+ cm::GenEx::Context const& context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries,
+ std::vector<cmLinkItem> const& libraries)
+{
+ for (cmLinkItem const& lib : libraries) {
+ if (lib.Target) {
+ EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+ // caller's property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cm::GenEx::Evaluation eval(context, false, headTarget, headTarget, true,
+ lib.Backtrace);
+ cmExpandList(
+ lib.Target->GetGeneratorFileSets()->EvaluateInterfaceProperty(
+ type, prop, &eval, dagChecker),
+ ee.Values);
+ ee.ContextDependent = eval.HadContextSensitiveCondition;
+ entries.Entries.emplace_back(std::move(ee));
+ }
+ }
+}
}
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
@@ -108,3 +134,19 @@
}
}
}
+
+void AddInterfaceFileSetsEntries(cmGeneratorTarget const* headTarget,
+ cm::string_view type, std::string const& prop,
+ cm::GenEx::Context const& context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries)
+{
+ if (cmLinkImplementationLibraries const* impl =
+ headTarget->GetLinkImplementationLibraries(
+ context.Config, cmGeneratorTarget::UseTo::Compile)) {
+ entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
+ addInterfaceFileSetsEntry(headTarget, type, prop, context, dagChecker,
+ entries, impl->Libraries);
+ }
+}
+}
diff --git a/Source/cmEvaluatedTargetProperty.h b/Source/cmEvaluatedTargetProperty.h
index 1ffbec4..218793a 100644
--- a/Source/cmEvaluatedTargetProperty.h
+++ b/Source/cmEvaluatedTargetProperty.h
@@ -6,10 +6,14 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmGeneratorTarget.h"
#include "cmListFileCache.h"
namespace cm {
+class TargetPropertyEntry;
+
namespace GenEx {
struct Context;
}
@@ -18,6 +22,7 @@
class cmLinkItem;
struct cmGeneratorExpressionDAGChecker;
+namespace cm {
// Represent a target property entry after evaluating generator expressions
// and splitting up lists.
struct EvaluatedTargetPropertyEntry
@@ -40,8 +45,7 @@
EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
cmGeneratorTarget const* thisTarget, cm::GenEx::Context const& context,
- cmGeneratorExpressionDAGChecker* dagChecker,
- cmGeneratorTarget::TargetPropertyEntry& entry);
+ cmGeneratorExpressionDAGChecker* dagChecker, cm::TargetPropertyEntry& entry);
struct EvaluatedTargetPropertyEntries
{
@@ -52,8 +56,7 @@
EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
cmGeneratorTarget const* thisTarget, cm::GenEx::Context const& context,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
- in);
+ std::vector<std::unique_ptr<cm::TargetPropertyEntry>> const& in);
// IncludeRuntimeInterface is used to break the cycle in computing
// the necessary transitive dependencies of targets that can occur
@@ -82,3 +85,10 @@
EvaluatedTargetPropertyEntries& entries,
IncludeRuntimeInterface searchRuntime,
cmGeneratorTarget::UseTo usage = cmGeneratorTarget::UseTo::Compile);
+
+void AddInterfaceFileSetsEntries(cmGeneratorTarget const* headTarget,
+ cm::string_view type, std::string const& prop,
+ cm::GenEx::Context const& context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries);
+}
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 63dcb60..d5e9a3a 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -27,6 +27,8 @@
#include "cmsys/String.h"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
+#include "cmEnvironment.h"
#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
@@ -94,6 +96,8 @@
bool EchoOutputVariable = false;
bool EchoErrorVariable = false;
cm::optional<std::string> Encoding;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Environment;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> EnvModification;
std::string CommandErrorIsFatal;
};
@@ -117,6 +121,8 @@
.Bind("ERROR_STRIP_TRAILING_WHITESPACE"_s,
&Arguments::ErrorStripTrailingWhitespace)
.Bind("ENCODING"_s, &Arguments::Encoding)
+ .Bind("ENVIRONMENT"_s, &Arguments::Environment)
+ .Bind("ENVIRONMENT_MODIFICATION"_s, &Arguments::EnvModification)
.Bind("ECHO_OUTPUT_VARIABLE"_s, &Arguments::EchoOutputVariable)
.Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable)
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
@@ -213,6 +219,23 @@
builder.SetWorkingDirectory(arguments.WorkingDirectory);
}
+ if (!arguments.Environment.empty() || !arguments.EnvModification.empty()) {
+#ifndef CMAKE_BOOTSTRAP
+ auto diff = cmEnvironmentModification{};
+ if (!diff.Add(arguments.EnvModification)) {
+ return false;
+ }
+ auto env = cmEnvironment{ cmSystemTools::GetEnvironmentVariables() };
+ env.Update(arguments.Environment);
+ diff.ApplyTo(env);
+ builder.SetEnvironment(env.GetVariables());
+#else
+ status.SetError(
+ "does not support environment modification in bootstrap builds");
+ return false;
+#endif
+ }
+
// Check the output variables.
std::unique_ptr<FILE, int (*)(FILE*)> inputFile(nullptr, fclose);
if (!inputFilename.empty()) {
diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx
index acf8e5c..7d40c0b 100644
--- a/Source/cmExperimental.cxx
+++ b/Source/cmExperimental.cxx
@@ -64,7 +64,7 @@
cmExperimental::TryCompileCondition::Never },
// Rust support
{ "Rust",
- "3cc9b32c-47d3-4056-8953-d74e69fc0d6c",
+ "efaed83b-d73a-48af-999a-bd0a6172c313",
"CMAKE_EXPERIMENTAL_RUST",
"CMake's support for the Rust programming language is experimental. "
"It is meant only for experimentation and feedback to CMake developers.",
diff --git a/Source/cmExportBuildCMakeConfigGenerator.cxx b/Source/cmExportBuildCMakeConfigGenerator.cxx
index b163eae..6ca639c 100644
--- a/Source/cmExportBuildCMakeConfigGenerator.cxx
+++ b/Source/cmExportBuildCMakeConfigGenerator.cxx
@@ -2,25 +2,23 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmExportBuildCMakeConfigGenerator.h"
-#include <algorithm>
#include <cstddef>
#include <functional>
#include <map>
-#include <memory>
+#include <ostream>
#include <set>
-#include <sstream>
#include <utility>
#include <vector>
#include <cm/string_view>
-#include <cmext/string_view>
#include "cmCryptoHash.h"
#include "cmExportSet.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
@@ -73,12 +71,17 @@
return false;
}
+ ImportFileSetPropertyMap fsProperties;
+ if (!this->PopulateFileSetInterfaceProperties(gte, fsProperties)) {
+ return false;
+ }
+
this->PopulateInterfaceLinkLibrariesProperty(
gte, cmGeneratorExpression::BuildInterface, properties);
this->GenerateInterfaceProperties(gte, os, properties);
- this->GenerateTargetFileSets(gte, os);
+ this->GenerateTargetFileSets(gte, os, fsProperties);
}
std::string cxx_modules_name;
@@ -160,47 +163,35 @@
}
}
-namespace {
-bool EntryIsContextSensitive(
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
-{
- return cge->GetHadContextSensitiveCondition();
-}
-}
-
std::string cmExportBuildCMakeConfigGenerator::GetFileSetDirectories(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*te*/)
+ cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet,
+ cmTargetExport const* /*te*/)
{
std::vector<std::string> resultVector;
auto configs =
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
- auto directoryEntries = fileSet->CompileDirectoryEntries();
for (auto const& config : configs) {
cm::GenEx::Context context(gte->LocalGenerator, config);
- auto directories =
- fileSet->EvaluateDirectoryEntries(directoryEntries, context, gte);
-
- bool const contextSensitive =
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
- EntryIsContextSensitive);
+ auto directories = fileSet->GetDirectories(context, gte);
+ bool const contextSensitive = directories.second;
auto const& type = fileSet->GetType();
// C++ modules do not support interface file sets which are dependent upon
// the configuration.
- if (contextSensitive && type == "CXX_MODULES"_s) {
+ if (contextSensitive && type == cm::FileSetMetadata::CXX_MODULES) {
auto* mf = this->LG->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive base directory entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("The \"", gte->GetName(),
+ "\" target's interface file set \"",
+ fileSet->GetName(), "\" of type \"", type,
+ "\" contains context-sensitive base directory "
+ "entries which is not supported."));
return std::string{};
}
- for (auto const& directory : directories) {
+ for (auto const& directory : directories.first) {
auto dest = cmOutputConverter::EscapeForCMake(
directory, cmOutputConverter::WrapQuotes::NoWrap);
@@ -217,47 +208,35 @@
}
std::string cmExportBuildCMakeConfigGenerator::GetFileSetFiles(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*te*/)
+ cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet,
+ cmTargetExport const* /*te*/)
{
std::vector<std::string> resultVector;
auto configs =
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
- auto fileEntries = fileSet->CompileFileEntries();
- auto directoryEntries = fileSet->CompileDirectoryEntries();
-
for (auto const& config : configs) {
cm::GenEx::Context context(gte->LocalGenerator, config);
- auto directories =
- fileSet->EvaluateDirectoryEntries(directoryEntries, context, gte);
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- fileSet->EvaluateFileEntry(directories, files, entry, context, gte);
- }
-
- bool const contextSensitive =
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
- EntryIsContextSensitive) ||
- std::any_of(fileEntries.begin(), fileEntries.end(),
- EntryIsContextSensitive);
+ auto files = fileSet->GetFiles(context, gte);
+ bool const contextSensitive = files.second;
auto const& type = fileSet->GetType();
// C++ modules do not support interface file sets which are dependent upon
// the configuration.
- if (contextSensitive && type == "CXX_MODULES"_s) {
+ if (contextSensitive && type == cm::FileSetMetadata::CXX_MODULES) {
auto* mf = this->LG->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive file entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("The \"", gte->GetName(),
+ "\" target's interface file set \"",
+ fileSet->GetName(), "\" of type \"", type,
+ "\" contains context-sensitive file entries "
+ "which is not supported."));
return std::string{};
}
- for (auto const& it : files) {
+ for (auto const& it : files.first) {
for (auto const& filename : it.second) {
auto escapedFile = cmOutputConverter::EscapeForCMake(
filename, cmOutputConverter::WrapQuotes::NoWrap);
@@ -317,9 +296,8 @@
cmGeneratedFileStream os(fileName, true);
if (!os) {
std::string se = cmSystemTools::GetLastSystemError();
- std::ostringstream e;
- e << "cannot write to file \"" << fileName << "\": " << se;
- cmSystemTools::Error(e.str());
+ cmSystemTools::Error(
+ cmStrCat("cannot write to file \"", fileName, "\": ", se));
return false;
}
os.SetCopyIfDifferent(true);
diff --git a/Source/cmExportBuildCMakeConfigGenerator.h b/Source/cmExportBuildCMakeConfigGenerator.h
index c625032..29ecb23 100644
--- a/Source/cmExportBuildCMakeConfigGenerator.h
+++ b/Source/cmExportBuildCMakeConfigGenerator.h
@@ -36,9 +36,11 @@
void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
std::string const& suffix) override;
- std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ std::string GetFileSetDirectories(cmGeneratorTarget* gte,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) override;
- std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ std::string GetFileSetFiles(cmGeneratorTarget* gte,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) override;
void GenerateCxxModuleConfigInformation(std::string const&,
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index ee12b1d..54b4ad5 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -11,6 +11,8 @@
#include "cmExportSet.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
@@ -21,7 +23,6 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
-#include "cmake.h"
class cmSourceFile;
@@ -244,8 +245,13 @@
void cmExportBuildFileGenerator::IssueMessage(MessageType type,
std::string const& message) const
{
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- type, message, this->LG->GetMakefile()->GetBacktrace());
+ this->LG->GetMakefile()->IssueMessage(type, message);
+}
+
+void cmExportBuildFileGenerator::IssueDiagnostic(
+ cmDiagnosticCategory category, std::string const& message) const
+{
+ this->LG->GetMakefile()->IssueDiagnostic(category, message);
}
std::string cmExportBuildFileGenerator::InstallNameDir(
@@ -280,3 +286,24 @@
return this->PopulateInterfaceProperties(
target, {}, cmGeneratorExpression::BuildInterface, properties);
}
+
+bool cmExportBuildFileGenerator::PopulateFileSetInterfaceProperties(
+ cmGeneratorTarget const* target, ImportFileSetPropertyMap& properties)
+{
+ cmGeneratorFileSets const* const gfs = target->GetGeneratorFileSets();
+ bool result = true;
+
+ for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
+ for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
+ ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
+ this->PopulateFileSetInterfaceProperty(
+ "INTERFACE_INCLUDE_DIRECTORIES", target, fileSet,
+ cmGeneratorExpression::BuildInterface, fsProperties);
+ result = result &&
+ this->PopulateFileSetInterfaceProperties(
+ target, fileSet, cmGeneratorExpression::InstallInterface,
+ fsProperties);
+ }
+ }
+ return result;
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 575d8e2..5e9e4c8 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -11,6 +11,7 @@
#include <cmext/algorithm>
+#include "cmDiagnostics.h"
#include "cmExportFileGenerator.h"
#include "cmStateTypes.h"
@@ -88,6 +89,8 @@
void IssueMessage(MessageType type,
std::string const& message) const override;
+ void IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& message) const override;
/** Fill in properties indicating built file locations. */
void SetImportLocationProperty(std::string const& config,
@@ -111,6 +114,10 @@
bool PopulateInterfaceProperties(cmGeneratorTarget const* target,
ImportPropertyMap& properties);
+ using cmExportFileGenerator::PopulateFileSetInterfaceProperties;
+ bool PopulateFileSetInterfaceProperties(
+ cmGeneratorTarget const* target, ImportFileSetPropertyMap& properties);
+
struct TargetExportPrivate
{
TargetExportPrivate(cmGeneratorTarget* target,
diff --git a/Source/cmExportCMakeConfigGenerator.cxx b/Source/cmExportCMakeConfigGenerator.cxx
index 83307d7..353d38f 100644
--- a/Source/cmExportCMakeConfigGenerator.cxx
+++ b/Source/cmExportCMakeConfigGenerator.cxx
@@ -5,6 +5,7 @@
#include <algorithm>
#include <cassert>
#include <sstream>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -13,14 +14,16 @@
#include <cmext/string_view>
#include "cmExportSet.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmFindPackageStack.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
+#include "cmScriptGenerator.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -173,7 +176,7 @@
// Isolate the file policy level.
// Support CMake versions as far back as the
// RequiredCMakeVersion{Major,Minor,Patch}, but also support using NEW
- // policy settings for up to CMake 4.1 (this upper limit may be reviewed
+ // policy settings for up to CMake 4.2 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
@@ -182,7 +185,7 @@
"cmake_policy(VERSION "
<< this->RequiredCMakeVersionMajor << '.'
<< this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << "...4.1)\n";
+ << this->RequiredCMakeVersionPatch << "...4.2)\n";
/* clang-format on */
}
@@ -471,7 +474,7 @@
if (it.second.Enabled == cmExportSet::PackageDependencyExportEnabled::On) {
os << "__find_dependency_no_return(" << it.first;
for (auto const& arg : it.second.ExtraArguments) {
- os << ' ' << cmOutputConverter::EscapeForCMake(arg);
+ os << ' ' << cmScriptGenerator::Quote(arg);
}
os << " ${_cmake_unwind_arg})\n";
os << "if(NOT " << it.first << "_FOUND)\n"
@@ -596,54 +599,94 @@
os << ")\n\n";
}
-void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
- cmGeneratorTarget* gte, std::ostream& os, cmTargetExport const* te)
+namespace {
+struct FileSetInformation
{
- auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
- if (!interfaceFileSets.empty()) {
+ cm::string_view Type;
+ cm::string_view CMakeVersion;
+};
+
+cm::optional<FileSetInformation> GetFileSetInformation(cm::string_view type)
+{
+ static std::unordered_map<cm::string_view, FileSetInformation>
+ fileSetsInformation{
+ { cm::FileSetMetadata::HEADERS,
+ { cm::FileSetMetadata::HEADERS, "3.23.0"_s } },
+ { cm::FileSetMetadata::SOURCES,
+ { cm::FileSetMetadata::SOURCES, "4.4.0"_s } },
+ { cm::FileSetMetadata::CXX_MODULES,
+ { cm::FileSetMetadata::CXX_MODULES, "3.28.0"_s } },
+ };
+
+ auto fsInfo = fileSetsInformation.find(type);
+ if (fsInfo != fileSetsInformation.end()) {
+ return fsInfo->second;
+ }
+ return {};
+}
+}
+
+void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
+ cmGeneratorTarget* gte, std::ostream& os,
+ ImportFileSetPropertyMap const& properties, cmTargetExport const* te)
+{
+ cmGeneratorFileSets const* gfs = gte->GetGeneratorFileSets();
+ auto const& types = gfs->GetInterfaceFileSetTypes();
+
+ if (!types.empty()) {
std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
- os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.23.0\")\n"
- " target_sources("
- << targetName << '\n';
+ for (auto const& type : types) {
+ auto fsInfo = GetFileSetInformation(type);
+ if (fsInfo) {
+ os << "if(NOT CMAKE_VERSION VERSION_LESS \"" << fsInfo->CMakeVersion
+ << "\")\n ";
+ }
+ os << "target_sources(" << targetName << '\n';
- 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;
+ for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
+ os << " INTERFACE"
+ << "\n FILE_SET "
+ << cmScriptGenerator::Quote(fileSet->GetName()) << "\n TYPE "
+ << cmScriptGenerator::Quote(type) << "\n BASE_DIRS "
+ << this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
+ << this->GetFileSetFiles(gte, fileSet, te) << '\n';
+ }
+ os << " )\n";
+ for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
+ auto fsProperties = properties.find(fileSet->GetName());
+ if (fsProperties != properties.end()) {
+ for (auto const& property : fsProperties->second) {
+ os << "\n set_property(FILE_SET "
+ << cmScriptGenerator::Quote(fileSet->GetName()) << " TARGET "
+ << targetName << "\n PROPERTY " << property.first << ' '
+ << cmExportFileGeneratorEscape(property.second) << "\n )";
+ }
+ }
}
- os << " INTERFACE"
- << "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name)
- << "\n TYPE "
- << cmOutputConverter::EscapeForCMake(fileSet->GetType())
- << "\n BASE_DIRS "
- << this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
- << this->GetFileSetFiles(gte, fileSet, te) << '\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;
- }
-
- if (fileSet->GetType() == "HEADERS"_s) {
- os << "\n " << this->GetFileSetDirectories(gte, fileSet, te);
+ if (fsInfo) {
+ if (type == cm::FileSetMetadata::HEADERS) {
+ os << "\nelse()\n set_property(TARGET " << targetName
+ << "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES";
+ for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
+ os << "\n " << this->GetFileSetDirectories(gte, fileSet, te);
+ }
+ os << "\n )";
+ } else if (type == cm::FileSetMetadata::SOURCES) {
+ os << "\nelse()\n message(FATAL_ERROR \"The target '" << targetName
+ << "' cannot be imported because it relies on 'FILE_SET' of type "
+ "'SOURCES' which is not supported by this CMake version.\")";
+ } else if (type == cm::FileSetMetadata::CXX_MODULES) {
+ os << "\nelse()\n message(AUTHOR_WARNING \"The target '"
+ << targetName
+ << "' cannot be imported properly because it relies on C++ "
+ "modules which are not supported by this CMake version.\")";
+ }
+ os << "\nendif()\n\n";
+ } else {
+ os << ")\n\n";
}
}
- os << "\n )\nendif()\n\n";
}
}
diff --git a/Source/cmExportCMakeConfigGenerator.h b/Source/cmExportCMakeConfigGenerator.h
index f95676f..b2401e5 100644
--- a/Source/cmExportCMakeConfigGenerator.h
+++ b/Source/cmExportCMakeConfigGenerator.h
@@ -15,7 +15,7 @@
#include "cmGeneratorExpression.h"
#include "cmStateTypes.h"
-class cmFileSet;
+class cmGeneratorFileSet;
class cmGeneratorTarget;
class cmTargetExport;
@@ -44,6 +44,7 @@
protected:
using ImportPropertyMap = std::map<std::string, std::string>;
+ using ImportFileSetPropertyMap = std::map<std::string, ImportPropertyMap>;
// Methods to implement export file code generation.
bool GenerateImportFile(std::ostream& os) override;
@@ -84,6 +85,7 @@
cmGeneratorTarget const* target, ImportPropertyMap& properties);
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
+ ImportFileSetPropertyMap const& properties,
cmTargetExport const* te = nullptr);
std::string GetCxxModuleFile(std::string const& name) const override;
@@ -91,10 +93,10 @@
void GenerateCxxModuleInformation(std::string const& name, std::ostream& os);
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
- cmFileSet* fileSet,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) = 0;
virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
- cmFileSet* fileSet,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) = 0;
void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index fdf0dbd..aeb68a3 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmComputeLinkInformation.h"
#include "cmFindPackageStack.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmList.h"
@@ -139,6 +140,20 @@
return true;
}
+bool cmExportFileGenerator::PopulateFileSetInterfaceProperties(
+ cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
+{
+ this->PopulateFileSetInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
+ target, fileSet, preprocessRule,
+ properties);
+ this->PopulateFileSetInterfaceProperty("INTERFACE_COMPILE_OPTIONS", target,
+ fileSet, preprocessRule, properties);
+
+ return true;
+}
+
void cmExportFileGenerator::PopulateInterfaceProperty(
std::string const& propName, cmGeneratorTarget const* target,
ImportPropertyMap& properties) const
@@ -181,6 +196,29 @@
properties);
}
+void cmExportFileGenerator::PopulateFileSetInterfaceProperty(
+ std::string const& propName, cmGeneratorTarget const* target,
+ cmGeneratorFileSet const* fileSet,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
+{
+ cmValue input = fileSet->GetProperty(propName);
+ if (input) {
+ if (input->empty()) {
+ // Set to empty
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(*input, preprocessRule);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target);
+ properties[propName] = prepro;
+ }
+ }
+}
+
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
@@ -674,9 +712,9 @@
bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
cmGeneratorExpression::PreprocessContext ctx,
- std::string const& includesDestinationDirs, std::string& errorMessage)
+ std::string const& includesDestinationDirs, std::string&)
{
- if (!gte->HaveCxx20ModuleSources(&errorMessage)) {
+ if (!gte->HaveCxx20ModuleSources()) {
return true;
}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index f53cba7..814fd54 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -12,11 +12,13 @@
#include <cm/string_view>
+#include "cmDiagnostics.h"
#include "cmGeneratorExpression.h"
#include "cmMessageType.h"
class cmExportSet;
class cmGeneratorTarget;
+class cmGeneratorFileSet;
class cmLocalGenerator;
/** \class cmExportFileGenerator
@@ -47,6 +49,7 @@
protected:
using ImportPropertyMap = std::map<std::string, std::string>;
+ using ImportFileSetPropertyMap = std::map<std::string, ImportPropertyMap>;
// Collect properties with detailed information about targets beyond
// their location on disk.
@@ -111,6 +114,10 @@
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
+ void PopulateFileSetInterfaceProperty(
+ std::string const& propName, cmGeneratorTarget const* target,
+ cmGeneratorFileSet const* fileSet,
+ cmGeneratorExpression::PreprocessContext, ImportPropertyMap& properties);
bool PopulateInterfaceLinkLibrariesProperty(
cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
@@ -121,8 +128,15 @@
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
+ bool PopulateFileSetInterfaceProperties(
+ cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
+
virtual void IssueMessage(MessageType type,
std::string const& message) const = 0;
+ virtual void IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& message) const = 0;
void ReportError(std::string const& errorMessage) const
{
diff --git a/Source/cmExportInstallCMakeConfigGenerator.cxx b/Source/cmExportInstallCMakeConfigGenerator.cxx
index d803121..eae42b6 100644
--- a/Source/cmExportInstallCMakeConfigGenerator.cxx
+++ b/Source/cmExportInstallCMakeConfigGenerator.cxx
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmExportInstallCMakeConfigGenerator.h"
-#include <algorithm>
#include <functional>
#include <map>
#include <memory>
@@ -12,14 +11,14 @@
#include <vector>
#include <cm/string_view>
-#include <cmext/string_view>
#include "cmExportFileGenerator.h"
#include "cmExportSet.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -84,6 +83,11 @@
return false;
}
+ ImportFileSetPropertyMap fsProperties;
+ if (!this->PopulateFileSetInterfaceProperties(te, fsProperties)) {
+ return false;
+ }
+
if (this->PopulateInterfaceLinkLibrariesProperty(
gt, cmGeneratorExpression::InstallInterface, properties) &&
!this->ExportOld) {
@@ -100,7 +104,7 @@
this->GenerateInterfaceProperties(gt, os, properties);
- this->GenerateTargetFileSets(gt, os, te);
+ this->GenerateTargetFileSets(gt, os, fsProperties, te);
}
this->LoadConfigFiles(os);
@@ -271,16 +275,9 @@
}
}
-namespace {
-bool EntryIsContextSensitive(
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
-{
- return cge->GetHadContextSensitiveCondition();
-}
-}
-
std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te)
+ cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet,
+ cmTargetExport const* te)
{
std::vector<std::string> resultVector;
@@ -302,7 +299,8 @@
auto const& type = fileSet->GetType();
// C++ modules do not support interface file sets which are dependent upon
// the configuration.
- if (cge->GetHadContextSensitiveCondition() && type == "CXX_MODULES"_s) {
+ if (cge->GetHadContextSensitiveCondition() &&
+ type == cm::FileSetMetadata::CXX_MODULES) {
auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
std::ostringstream e;
e << "The \"" << gte->GetName() << "\" target's interface file set \""
@@ -326,29 +324,22 @@
}
std::string cmExportInstallCMakeConfigGenerator::GetFileSetFiles(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te)
+ cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet,
+ cmTargetExport const* te)
{
std::vector<std::string> resultVector;
auto configs =
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
- auto fileEntries = fileSet->CompileFileEntries();
- auto directoryEntries = fileSet->CompileDirectoryEntries();
-
cmGeneratorExpression destGe(*gte->Makefile->GetCMakeInstance());
auto destCge = destGe.Parse(
te->FileSetGenerators.at(fileSet->GetName())->GetDestination());
for (auto const& config : configs) {
cm::GenEx::Context context(gte->LocalGenerator, config);
- auto directories =
- fileSet->EvaluateDirectoryEntries(directoryEntries, context, gte);
+ auto files = fileSet->GetFiles(context, gte);
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- fileSet->EvaluateFileEntry(directories, files, entry, context, gte);
- }
auto unescapedDest = destCge->Evaluate(gte->LocalGenerator, config, gte);
auto dest =
cmStrCat(cmOutputConverter::EscapeForCMake(
@@ -358,27 +349,23 @@
dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
}
- bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
- EntryIsContextSensitive) ||
- std::any_of(fileEntries.begin(), fileEntries.end(),
- EntryIsContextSensitive);
-
+ bool const contextSensitive =
+ destCge->GetHadContextSensitiveCondition() || files.second;
auto const& type = fileSet->GetType();
// C++ modules do not support interface file sets which are dependent upon
// the configuration.
- if (contextSensitive && type == "CXX_MODULES"_s) {
+ if (contextSensitive && type == cm::FileSetMetadata::CXX_MODULES) {
auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive base file entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("The \"", gte->GetName(),
+ "\" target's interface file set \"",
+ fileSet->GetName(), "\" of type \"", type,
+ "\" contains context-sensitive base file "
+ "entries which is not supported."));
return std::string{};
}
- for (auto const& it : files) {
+ for (auto const& it : files.first) {
auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
for (auto const& filename : it.second) {
auto relFile =
diff --git a/Source/cmExportInstallCMakeConfigGenerator.h b/Source/cmExportInstallCMakeConfigGenerator.h
index 480384d..e4ebd29 100644
--- a/Source/cmExportInstallCMakeConfigGenerator.h
+++ b/Source/cmExportInstallCMakeConfigGenerator.h
@@ -59,9 +59,11 @@
virtual void CleanupTemporaryVariables(std::ostream&);
- std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ std::string GetFileSetDirectories(cmGeneratorTarget* gte,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) override;
- std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ std::string GetFileSetFiles(cmGeneratorTarget* gte,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) override;
std::string GetCxxModulesDirectory() const override;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index db75480..c63f8a9 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -12,6 +12,8 @@
#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallTargetGenerator.h"
@@ -24,7 +26,6 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
-#include "cmake.h"
cmExportInstallFileGenerator::cmExportInstallFileGenerator(
cmInstallExportGenerator* iegen)
@@ -338,9 +339,15 @@
void cmExportInstallFileGenerator::IssueMessage(
MessageType type, std::string const& message) const
{
- this->IEGen->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- type, message,
- this->IEGen->GetLocalGenerator()->GetMakefile()->GetBacktrace());
+ cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
+ lg->GetMakefile()->IssueMessage(type, message);
+}
+
+void cmExportInstallFileGenerator::IssueDiagnostic(
+ cmDiagnosticCategory category, std::string const& message) const
+{
+ cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
+ lg->GetMakefile()->IssueDiagnostic(category, message);
}
std::string cmExportInstallFileGenerator::InstallNameDir(
@@ -405,6 +412,27 @@
properties);
}
+bool cmExportInstallFileGenerator::PopulateFileSetInterfaceProperties(
+ cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties)
+{
+ cmGeneratorTarget const* const gt = targetExport->Target;
+ cmGeneratorFileSets const* const gfs = gt->GetGeneratorFileSets();
+
+ bool result = true;
+
+ for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
+ for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
+ ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
+ this->PopulateFileSetIncludeDirectoriesInterface(
+ gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
+ result = result &&
+ this->PopulateFileSetInterfaceProperties(
+ gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
+ }
+ }
+ return result;
+}
+
namespace {
bool isSubDirectory(std::string const& a, std::string const& b)
{
@@ -615,6 +643,37 @@
}
}
+void cmExportInstallFileGenerator::PopulateFileSetIncludeDirectoriesInterface(
+ cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
+{
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
+ cmValue includes = fileSet->GetProperty(propName);
+
+ if (!includes) {
+ return;
+ }
+ if (includes && includes->empty()) {
+ // Set to empty
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro = cmGeneratorExpression::Preprocess(
+ *includes, preprocessRule, this->GetImportPrefixWithSlash());
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target);
+
+ if (!this->CheckInterfaceDirs(prepro, target, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
cmGeneratorTarget const* gt,
cmGeneratorExpression::PreprocessContext preprocessRule,
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 5a72903..baee785 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -12,12 +12,14 @@
#include <cm/string_view>
+#include "cmDiagnostics.h"
#include "cmExportFileGenerator.h"
#include "cmGeneratorExpression.h"
#include "cmInstallExportGenerator.h"
#include "cmStateTypes.h"
class cmGeneratorTarget;
+class cmGeneratorFileSet;
class cmInstallTargetGenerator;
class cmTargetExport;
@@ -96,6 +98,8 @@
void IssueMessage(MessageType type,
std::string const& message) const override;
+ void IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& message) const override;
/** Generate a per-configuration file for the targets. */
virtual bool GenerateImportFileConfig(std::string const& config);
@@ -135,6 +139,10 @@
ImportPropertyMap& properties,
std::set<std::string>& importedLocations);
+ using cmExportFileGenerator::PopulateFileSetInterfaceProperties;
+ bool PopulateFileSetInterfaceProperties(
+ cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties);
+
virtual bool CheckInterfaceDirs(std::string const& prepro,
cmGeneratorTarget const* target,
std::string const& prop) const;
@@ -176,4 +184,9 @@
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
+
+ void PopulateFileSetIncludeDirectoriesInterface(
+ cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
};
diff --git a/Source/cmExportInstallPackageInfoGenerator.cxx b/Source/cmExportInstallPackageInfoGenerator.cxx
index f14942d..78eb146 100644
--- a/Source/cmExportInstallPackageInfoGenerator.cxx
+++ b/Source/cmExportInstallPackageInfoGenerator.cxx
@@ -19,8 +19,9 @@
#include "cmAlgorithms.h"
#include "cmExportSet.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -220,8 +221,8 @@
cm::optional<std::string>
cmExportInstallPackageInfoGenerator::GetFileSetDirectory(
- cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet,
- cm::optional<std::string> const& config)
+ cmGeneratorTarget* gte, cmTargetExport const* te,
+ cmGeneratorFileSet const* fileSet, cm::optional<std::string> const& config)
{
cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
auto cge =
@@ -240,7 +241,7 @@
}
std::string const& type = fileSet->GetType();
- if (config && (type == "CXX_MODULES"_s)) {
+ if (config && (type == cm::FileSetMetadata::CXX_MODULES)) {
// C++ modules do not support interface file sets which are dependent
// upon the configuration.
cmMakefile* mf = gte->LocalGenerator->GetMakefile();
@@ -270,7 +271,7 @@
bool hasModules = false;
std::set<std::string> seenIncludeDirectories;
for (auto const& name : gte->Target->GetAllInterfaceFileSets()) {
- cmFileSet* fileSet = gte->Target->GetFileSet(name);
+ cmGeneratorFileSet const* fileSet = gte->GetFileSet(name);
if (!fileSet) {
gte->Makefile->IssueMessage(
@@ -284,13 +285,13 @@
cm::optional<std::string> const& fileSetDirectory =
this->GetFileSetDirectory(gte, te, fileSet, config);
- if (fileSet->GetType() == "HEADERS"_s) {
+ if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
if (fileSetDirectory &&
!cm::contains(seenIncludeDirectories, *fileSetDirectory)) {
component["includes"].append(*fileSetDirectory);
seenIncludeDirectories.insert(*fileSetDirectory);
}
- } else if (fileSet->GetType() == "CXX_MODULES"_s) {
+ } else if (fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES) {
hasModules = true;
this->RequiresConfigFiles = true;
}
diff --git a/Source/cmExportInstallPackageInfoGenerator.h b/Source/cmExportInstallPackageInfoGenerator.h
index 1501234..da7f4e3 100644
--- a/Source/cmExportInstallPackageInfoGenerator.h
+++ b/Source/cmExportInstallPackageInfoGenerator.h
@@ -12,7 +12,7 @@
#include "cmExportInstallFileGenerator.h"
#include "cmExportPackageInfoGenerator.h"
-class cmFileSet;
+class cmGeneratorFileSet;
class cmGeneratorTarget;
class cmInstallExportGenerator;
class cmPackageInfoArguments;
@@ -71,7 +71,8 @@
std::string GetCxxModulesDirectory() const override;
cm::optional<std::string> GetFileSetDirectory(
- cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet,
+ cmGeneratorTarget* gte, cmTargetExport const* te,
+ cmGeneratorFileSet const* fileSet,
cm::optional<std::string> const& config = {});
bool GenerateFileSetProperties(Json::Value& component,
diff --git a/Source/cmExportInstallSbomGenerator.cxx b/Source/cmExportInstallSbomGenerator.cxx
index c5c9acb..d944383 100644
--- a/Source/cmExportInstallSbomGenerator.cxx
+++ b/Source/cmExportInstallSbomGenerator.cxx
@@ -13,8 +13,9 @@
#include <cmext/string_view>
#include "cmExportSet.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -212,8 +213,8 @@
}
cm::optional<std::string> cmExportInstallSbomGenerator::GetFileSetDirectory(
- cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet,
- cm::optional<std::string> const& config)
+ cmGeneratorTarget* gte, cmTargetExport const* te,
+ cmGeneratorFileSet const* fileSet, cm::optional<std::string> const& config)
{
cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
auto cge =
@@ -228,7 +229,7 @@
}
std::string const& type = fileSet->GetType();
- if (config && (type == "CXX_MODULES"_s)) {
+ if (config && (type == cm::FileSetMetadata::CXX_MODULES)) {
cmMakefile* mf = gte->LocalGenerator->GetMakefile();
std::ostringstream e;
e << "The \"" << gte->GetName() << "\" target's interface file set \""
diff --git a/Source/cmExportInstallSbomGenerator.h b/Source/cmExportInstallSbomGenerator.h
index c7fb9b6..a6d4c5c 100644
--- a/Source/cmExportInstallSbomGenerator.h
+++ b/Source/cmExportInstallSbomGenerator.h
@@ -13,7 +13,7 @@
#include "cmExportInstallFileGenerator.h"
#include "cmExportSbomGenerator.h"
-class cmFileSet;
+class cmGeneratorFileSet;
class cmGeneratorTarget;
class cmInstallExportGenerator;
class cmSbomArguments;
@@ -63,6 +63,7 @@
std::string GetCxxModulesDirectory() const override;
cm::optional<std::string> GetFileSetDirectory(
- cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet,
+ cmGeneratorTarget* gte, cmTargetExport const* te,
+ cmGeneratorFileSet const* fileSet,
cm::optional<std::string> const& config = {});
};
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index 886c639..ec1d076 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -6,12 +6,13 @@
#include <utility>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/string_view>
-#include "cmFileSet.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
@@ -54,6 +55,15 @@
}
}
+void cmExportTryCompileFileGenerator::IssueDiagnostic(
+ cmDiagnosticCategory category, std::string const& message) const
+{
+ cm::string_view const cname =
+ cmDiagnostics::GetCategoryString(category).substr(4);
+ cmSystemTools::Message(
+ cmStrCat("CMake Diagnostic ("_s, cname, "): "_s, message), "Diagnostic");
+}
+
bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
{
std::set<cmGeneratorTarget const*> emitted;
@@ -176,14 +186,16 @@
}
std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
- cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport const* /*te*/)
+ cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet,
+ cmTargetExport const* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmList::to_string(fileSet->GetDirectoryEntries()));
}
std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
- cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport const* /*te*/)
+ cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet,
+ cmTargetExport const* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmList::to_string(fileSet->GetFileEntries()));
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 00231ba..432a53c 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "cmDiagnostics.h"
#include "cmExportCMakeConfigGenerator.h"
class cmGeneratorTarget;
@@ -32,6 +33,8 @@
std::string const& /*targetName*/) const override {};
void IssueMessage(MessageType type,
std::string const& message) const override;
+ void IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& message) const override;
bool GenerateMainFile(std::ostream& os) override;
@@ -57,10 +60,11 @@
std::string const& config) override;
std::string GetFileSetDirectories(cmGeneratorTarget* target,
- cmFileSet* fileSet,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) override;
- std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
+ std::string GetFileSetFiles(cmGeneratorTarget* target,
+ cmGeneratorFileSet const* fileSet,
cmTargetExport const* te) override;
std::string GetCxxModulesDirectory() const override { return {}; }
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index e2a2553..7c946f2 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -100,6 +100,11 @@
this->ErrorString = ostr.str();
}
+void cmExprParserHelper::Warning(std::string str)
+{
+ this->WarningString = cmStrCat(this->WarningString, std::move(str), '\n');
+}
+
void cmExprParserHelper::UnexpectedChar(char c)
{
unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
@@ -109,7 +114,7 @@
this->WarningString += ostr.str();
}
-void cmExprParserHelper::SetResult(KWIML_INT_int64_t value)
+void cmExprParserHelper::SetResult(std::int64_t value)
{
this->Result = value;
}
@@ -118,3 +123,159 @@
{
this->ErrorString = std::move(errorString);
}
+
+std::int64_t cmExprParserHelper::ShL(std::int64_t l, std::int64_t r)
+{
+ if (l < 0) {
+ this->Warning(
+ cmStrCat("left shift of negative value in:\n ", l, " << ", r));
+ }
+ if (r < 0) {
+ this->Warning(
+ cmStrCat("shift exponent is negative in:\n ", l, " << ", r));
+ r &= 0x3F;
+ }
+ if (r >= 64) {
+ this->Warning(
+ cmStrCat("shift exponent is too large in:\n ", l, " << ", r));
+ r &= 0x3F;
+ }
+ return static_cast<std::int64_t>(static_cast<std::uint64_t>(l) << r);
+}
+
+std::int64_t cmExprParserHelper::ShR(std::int64_t l, std::int64_t r)
+{
+ if (r < 0) {
+ this->Warning(
+ cmStrCat("shift exponent is negative in:\n ", l, " >> ", r));
+ r &= 0x3F;
+ }
+ if (r >= 64) {
+ this->Warning(
+ cmStrCat("shift exponent is too large in:\n ", l, " >> ", r));
+ r &= 0x3F;
+ }
+ return l >> r;
+}
+
+std::int64_t cmExprParserHelper::Add(std::int64_t l, std::int64_t r)
+{
+ std::int64_t sum;
+ if (this->AddOverflow(l, r, &sum)) {
+ this->Warning(cmStrCat("signed integer overflow in:\n ", l, " + ", r));
+ }
+ return sum;
+}
+
+std::int64_t cmExprParserHelper::Sub(std::int64_t l, std::int64_t r)
+{
+ std::int64_t diff;
+ if (this->SubOverflow(l, r, &diff)) {
+ this->Warning(cmStrCat("signed integer overflow in:\n ", l, " - ", r));
+ }
+ return diff;
+}
+
+std::int64_t cmExprParserHelper::Mul(std::int64_t l, std::int64_t r)
+{
+ std::int64_t prod;
+ if (this->MulOverflow(l, r, &prod)) {
+ this->Warning(cmStrCat("signed integer overflow in:\n ", l, " * ", r));
+ }
+ return prod;
+}
+
+std::int64_t cmExprParserHelper::Div(std::int64_t l, std::int64_t r)
+{
+ if (r == 0) {
+ throw std::overflow_error("divide by zero");
+ }
+ return l / r;
+}
+
+std::int64_t cmExprParserHelper::Mod(std::int64_t l, std::int64_t r)
+{
+ if (r == 0) {
+ throw std::overflow_error("modulo by zero");
+ }
+ return l % r;
+}
+
+std::int64_t cmExprParserHelper::Neg(std::int64_t x)
+{
+ if (static_cast<std::uint64_t>(x) == 0x8000000000000000) {
+ this->Warning(cmStrCat("signed integer cannot negate:\n ", x));
+ return x;
+ }
+ return -x;
+}
+
+// The __has_builtin preprocessor check was added in Clang 2.6 and GCC 10.
+// The __builtin_X_overflow intrinsics were added in Clang 3.4 and GCC 5.
+#ifndef __has_builtin
+# if defined(__GNUC__) && __GNUC__ >= 5
+# define __has_builtin(x) 1
+# else
+# define __has_builtin(x) 0
+# endif
+#endif
+
+bool cmExprParserHelper::AddOverflow(long l, long r, long* p)
+{
+#if __has_builtin(__builtin_saddl_overflow)
+ return __builtin_saddl_overflow(l, r, p);
+#else
+ *p = l + r;
+ return false;
+#endif
+}
+
+bool cmExprParserHelper::AddOverflow(long long l, long long r, long long* p)
+{
+#if __has_builtin(__builtin_saddll_overflow)
+ return __builtin_saddll_overflow(l, r, p);
+#else
+ *p = l + r;
+ return false;
+#endif
+}
+
+bool cmExprParserHelper::SubOverflow(long l, long r, long* p)
+{
+#if __has_builtin(__builtin_ssubl_overflow)
+ return __builtin_ssubl_overflow(l, r, p);
+#else
+ *p = l - r;
+ return false;
+#endif
+}
+
+bool cmExprParserHelper::SubOverflow(long long l, long long r, long long* p)
+{
+#if __has_builtin(__builtin_ssubll_overflow)
+ return __builtin_ssubll_overflow(l, r, p);
+#else
+ *p = l - r;
+ return false;
+#endif
+}
+
+bool cmExprParserHelper::MulOverflow(long l, long r, long* p)
+{
+#if __has_builtin(__builtin_smull_overflow)
+ return __builtin_smull_overflow(l, r, p);
+#else
+ *p = l * r;
+ return false;
+#endif
+}
+
+bool cmExprParserHelper::MulOverflow(long long l, long long r, long long* p)
+{
+#if __has_builtin(__builtin_smulll_overflow)
+ return __builtin_smulll_overflow(l, r, p);
+#else
+ *p = l * r;
+ return false;
+#endif
+}
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index 54ef7fd..94c0b68 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -4,17 +4,16 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstdint>
#include <string>
#include <vector>
-#include <cm3p/kwiml/int.h>
-
class cmExprParserHelper
{
public:
struct ParserType
{
- KWIML_INT_int64_t Number;
+ std::int64_t Number;
};
cmExprParserHelper();
@@ -24,10 +23,11 @@
int LexInput(char* buf, int maxlen);
void Error(char const* str);
+ void Warning(std::string str);
- void SetResult(KWIML_INT_int64_t value);
+ void SetResult(std::int64_t value);
- KWIML_INT_int64_t GetResult() const { return this->Result; }
+ std::int64_t GetResult() const { return this->Result; }
char const* GetError() { return this->ErrorString.c_str(); }
@@ -35,6 +35,22 @@
std::string const& GetWarning() const { return this->WarningString; }
+ std::int64_t ShL(std::int64_t l, std::int64_t r);
+ std::int64_t ShR(std::int64_t l, std::int64_t r);
+ std::int64_t Add(std::int64_t l, std::int64_t r);
+ std::int64_t Sub(std::int64_t l, std::int64_t r);
+ std::int64_t Mul(std::int64_t l, std::int64_t r);
+ std::int64_t Div(std::int64_t l, std::int64_t r);
+ std::int64_t Mod(std::int64_t l, std::int64_t r);
+ std::int64_t Neg(std::int64_t x);
+
+ static bool AddOverflow(long l, long r, long* p);
+ static bool AddOverflow(long long l, long long r, long long* p);
+ static bool SubOverflow(long l, long r, long* p);
+ static bool SubOverflow(long long l, long long r, long long* p);
+ static bool MulOverflow(long l, long r, long* p);
+ static bool MulOverflow(long long l, long long r, long long* p);
+
private:
std::string::size_type InputBufferPos;
std::string InputBuffer;
@@ -46,7 +62,7 @@
void SetError(std::string errorString);
- KWIML_INT_int64_t Result;
+ std::int64_t Result;
char const* FileName;
long FileLine;
std::string ErrorString;
diff --git a/Source/cmFastbuildNormalTargetGenerator.cxx b/Source/cmFastbuildNormalTargetGenerator.cxx
index ee9e9fb..6aa2ee4 100644
--- a/Source/cmFastbuildNormalTargetGenerator.cxx
+++ b/Source/cmFastbuildNormalTargetGenerator.cxx
@@ -27,6 +27,8 @@
#include "cmFastbuildTargetGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalFastbuildGenerator.h"
@@ -117,7 +119,20 @@
cmGeneratorExpressionInterpreter genexInterpreter(
this->GetLocalGenerator(), Config, this->GeneratorTarget, language);
+ auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ this->Config, &srcFile);
+
std::vector<std::string> sourceIncludesVec;
+ if (fileSet) {
+ auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetIncludeDirectories(this->Config, language)
+ : fileSet->GetInterfaceIncludeDirectories(this->Config, language);
+ if (!fsIncludes.empty()) {
+ this->LocalGenerator->AppendIncludeDirectories(
+ sourceIncludesVec, cm::remove_BT(fsIncludes), srcFile);
+ }
+ }
if (cmValue cincludes = srcFile.GetProperty(INCLUDE_DIRECTORIES)) {
this->LocalGenerator->AppendIncludeDirectories(
sourceIncludesVec,
@@ -140,6 +155,17 @@
this->LocalGenerator->AppendCompileOptions(
compileFlags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
}
+ // Add flags from file set properties.
+ if (fileSet) {
+ auto options = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileOptions(this->Config, language)
+ : fileSet->GetInterfaceCompileOptions(this->Config, language);
+ if (!options.empty()) {
+ this->LocalGenerator->AppendCompileOptions(compileFlags,
+ cm::remove_BT(options));
+ }
+ }
+
// Source includes take precedence over target includes.
this->LocalGenerator->AppendFlags(compileFlags, sourceIncludesStr);
this->LocalGenerator->AppendFlags(compileFlags,
@@ -411,6 +437,17 @@
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS));
}
+ if (auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ this->Config, &srcFile)) {
+ auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileDefinitions(this->Config, language)
+ : fileSet->GetInterfaceCompileDefinitions(this->Config, language);
+ if (!fsDefines.empty()) {
+ this->LocalGenerator->AppendDefines(defines, fsDefines);
+ }
+ }
+
std::string definesString = this->GetDefines(language, Config);
LogMessage(cmStrCat("TARGET DEFINES = ", definesString));
this->GetLocalGenerator()->JoinDefines(defines, definesString, language);
diff --git a/Source/cmFastbuildTargetGenerator.cxx b/Source/cmFastbuildTargetGenerator.cxx
index 06f6ab9..2c008bb 100644
--- a/Source/cmFastbuildTargetGenerator.cxx
+++ b/Source/cmFastbuildTargetGenerator.cxx
@@ -356,7 +356,8 @@
for (auto dep : ccg.GetDepends()) {
LogMessage("Dep: " + dep);
auto orig = dep;
- if (this->LocalCommonGenerator->GetRealDependency(dep, Config, dep)) {
+ if (this->LocalCommonGenerator->GetRealDependency(
+ dep, Config, dep, ccg.GetCC().GetCMP0212Status())) {
LogMessage("Real dep: " + dep);
if (!dep.empty()) {
LogMessage("Custom command real dep: " + dep);
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index fa9c1c5..be816d5 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -148,10 +148,11 @@
std::vector<std::string> files;
cmsys::Directory d;
d.Load(dir);
+ files.reserve(d.GetNumberOfFiles());
for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
- std::string f = d.GetFile(i);
+ std::string const& f = d.GetFileName(i);
if (f != "." && f != "..") {
- files.push_back(std::move(f));
+ files.push_back(f);
}
}
std::sort(files.begin(), files.end());
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 2950c67..3d398b2 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -17,16 +17,16 @@
#include <cm/string_view>
#include <cmext/algorithm>
-#include <cmext/string_view>
#include <cm3p/json/value.h>
#include "cmCryptoHash.h"
#include "cmExportSet.h"
#include "cmFileAPI.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCxxModuleBmiGenerator.h"
@@ -48,7 +48,6 @@
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
@@ -465,7 +464,7 @@
using FileSetDatabase = std::map<std::string, Json::ArrayIndex>;
- std::vector<cmFileSetVisibility> FileSetVisibilities;
+ std::vector<cm::FileSetMetadata::Visibility> FileSetVisibilities;
template <typename T>
JBT<T> ToJBT(BT<T> const& bt)
@@ -502,7 +501,7 @@
Json::Value DumpLanguageStandard(JBTs<std::string> const& standard);
Json::Value DumpDefine(JBT<std::string> const& def);
std::pair<Json::Value, FileSetDatabase> DumpFileSets();
- Json::Value DumpFileSet(cmFileSet const* fs,
+ Json::Value DumpFileSet(cmGeneratorFileSet const* fs,
std::vector<std::string> const& directories);
Json::Value DumpSources(FileSetDatabase const& fsdb);
Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
@@ -1148,18 +1147,11 @@
auto* target = installFileSet->GetTarget();
cm::GenEx::Context context(target->LocalGenerator, this->Config);
-
- auto dirCges = fileSet->CompileDirectoryEntries();
- auto dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, target);
-
- auto entryCges = fileSet->CompileFileEntries();
- std::map<std::string, std::vector<std::string>> entries;
- for (auto const& entryCge : entryCges) {
- fileSet->EvaluateFileEntry(dirs, entries, entryCge, context, target);
- }
+ auto dirs = fileSet->GetDirectories(context, target);
+ auto entries = fileSet->GetFiles(context, target);
Json::Value files = Json::arrayValue;
- for (auto const& it : entries) {
+ for (auto const& it : entries.first) {
auto dir = it.first;
if (!dir.empty()) {
dir += '/';
@@ -1174,7 +1166,7 @@
installer["fileSetName"] = fileSet->GetName();
installer["fileSetType"] = fileSet->GetType();
installer["fileSetDirectories"] = Json::arrayValue;
- for (auto const& dir : dirs) {
+ for (auto const& dir : dirs.first) {
installer["fileSetDirectories"].append(
RelativeIfUnder(this->TopSource, dir));
}
@@ -1726,41 +1718,22 @@
this->FileSetVisibilities.clear();
// Build the fileset database.
- auto const* tgt = this->GT->Target;
- auto const& fs_names = tgt->GetAllFileSetNames();
+ auto const& fileSets = this->GT->GetAllFileSets();
- if (!fs_names.empty()) {
+ if (!fileSets.empty()) {
fsJson = Json::arrayValue;
size_t fsIndex = 0;
- for (auto const& fs_name : fs_names) {
- auto const* fs = tgt->GetFileSet(fs_name);
- if (!fs) {
- this->GT->Makefile->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("Target \"", tgt->GetName(),
- "\" is tracked to have file set \"", fs_name,
- "\", but it was not found."));
- continue;
- }
-
+ for (auto const* fs : fileSets) {
cm::GenEx::Context context(this->GT->LocalGenerator, this->Config);
- auto fileEntries = fs->CompileFileEntries();
- auto directoryEntries = fs->CompileDirectoryEntries();
+ auto directories = fs->GetDirectories(context, this->GT);
- auto directories =
- fs->EvaluateDirectoryEntries(directoryEntries, context, this->GT);
-
- fsJson.append(this->DumpFileSet(fs, directories));
+ fsJson.append(this->DumpFileSet(fs, directories.first));
this->FileSetVisibilities.push_back(fs->GetVisibility());
- std::map<std::string, std::vector<std::string>> files_per_dirs;
- for (auto const& entry : fileEntries) {
- fs->EvaluateFileEntry(directories, files_per_dirs, entry, context,
- this->GT);
- }
+ auto files_per_dirs = fs->GetFiles(context, this->GT);
- for (auto const& files_per_dir : files_per_dirs) {
+ for (auto const& files_per_dir : files_per_dirs.first) {
auto const& dir = files_per_dir.first;
for (auto const& file : files_per_dir.second) {
std::string sf_path;
@@ -1780,7 +1753,7 @@
return std::make_pair(fsJson, fsdb);
}
-Json::Value Target::DumpFileSet(cmFileSet const* fs,
+Json::Value Target::DumpFileSet(cmGeneratorFileSet const* fs,
std::vector<std::string> const& directories)
{
Json::Value fileSet = Json::objectValue;
@@ -1788,7 +1761,7 @@
fileSet["name"] = fs->GetName();
fileSet["type"] = fs->GetType();
fileSet["visibility"] =
- std::string(cmFileSetVisibilityToName(fs->GetVisibility()));
+ std::string(cm::FileSetMetadata::VisibilityToName(fs->GetVisibility()));
Json::Value baseDirs = Json::arrayValue;
for (auto const& directory : directories) {
@@ -1853,6 +1826,7 @@
case cmGeneratorTarget::SourceKindResx:
case cmGeneratorTarget::SourceKindXaml:
case cmGeneratorTarget::SourceKindUnityBatched:
+ case cmGeneratorTarget::SourceKindRustMainCrateRoot:
break;
}
@@ -1888,7 +1862,8 @@
Json::ArrayIndex const index = fsIter.second;
// FileSetVisibilities was populated by DumpFileSets() and will always
// have the same size as the file sets array that index is indexing into
- if (this->FileSetVisibilities[index] != cmFileSetVisibility::Private) {
+ if (this->FileSetVisibilities[index] !=
+ cm::FileSetMetadata::Visibility::Private) {
dumpFile(fsIter.first);
}
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 16cd19b..eec0ffd 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -3678,6 +3678,7 @@
std::string Format;
std::string Compression;
std::string CompressionLevel;
+ std::string Encoding;
// "MTIME" should require one value, but it has long been accidentally
// accepted without one and treated as if an empty value were given.
// Fixing this would require a policy.
@@ -3695,6 +3696,7 @@
.Bind("FORMAT"_s, &Arguments::Format)
.Bind("COMPRESSION"_s, &Arguments::Compression)
.Bind("COMPRESSION_LEVEL"_s, &Arguments::CompressionLevel)
+ .Bind("ENCODING"_s, &Arguments::Encoding)
.Bind("MTIME"_s, &Arguments::MTime)
.Bind("THREADS"_s, &Arguments::Threads)
.Bind("WORKING_DIRECTORY"_s, &Arguments::WorkingDirectory)
@@ -3822,10 +3824,19 @@
return false;
}
+ if (parsedArgs.Encoding.empty()) {
+ if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0213) ==
+ cmPolicies::NEW) {
+ parsedArgs.Encoding = "UTF-8";
+ } else {
+ parsedArgs.Encoding = "OEM";
+ }
+ }
+
if (!cmSystemTools::CreateTar(
parsedArgs.Output, parsedArgs.Paths, parsedArgs.WorkingDirectory,
- compress, parsedArgs.Verbose, parsedArgs.MTime, parsedArgs.Format,
- compressionLevel, threads)) {
+ compress, parsedArgs.Encoding, parsedArgs.Verbose, parsedArgs.MTime,
+ parsedArgs.Format, compressionLevel, threads)) {
status.SetError(cmStrCat("failed to compress: ", parsedArgs.Output));
cmSystemTools::SetFatalErrorOccurred();
return false;
@@ -3840,6 +3851,7 @@
struct Arguments : public ArgumentParser::ParseResult
{
std::string Input;
+ std::string Encoding;
bool Verbose = false;
bool ListOnly = false;
std::string Destination;
@@ -3849,6 +3861,7 @@
static auto const parser = cmArgumentParser<Arguments>{}
.Bind("INPUT"_s, &Arguments::Input)
+ .Bind("ENCODING"_s, &Arguments::Encoding)
.Bind("VERBOSE"_s, &Arguments::Verbose)
.Bind("LIST_ONLY"_s, &Arguments::ListOnly)
.Bind("DESTINATION"_s, &Arguments::Destination)
@@ -3872,9 +3885,18 @@
std::string inFile = parsedArgs.Input;
+ if (parsedArgs.Encoding.empty()) {
+ if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0213) ==
+ cmPolicies::NEW) {
+ parsedArgs.Encoding = "UTF-8";
+ } else {
+ parsedArgs.Encoding = "OEM";
+ }
+ }
+
if (parsedArgs.ListOnly) {
if (!cmSystemTools::ListTar(inFile, parsedArgs.Patterns,
- parsedArgs.Verbose)) {
+ parsedArgs.Encoding, parsedArgs.Verbose)) {
status.SetError(cmStrCat("failed to list: ", inFile));
cmSystemTools::SetFatalErrorOccurred();
return false;
@@ -3911,7 +3933,7 @@
inFile, parsedArgs.Patterns,
parsedArgs.Touch ? cmSystemTools::cmTarExtractTimestamps::No
: cmSystemTools::cmTarExtractTimestamps::Yes,
- parsedArgs.Verbose)) {
+ parsedArgs.Encoding, parsedArgs.Verbose)) {
status.SetError(cmStrCat("failed to extract:\n ", inFile));
cmSystemTools::SetFatalErrorOccurred();
return false;
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index c848ed7..28e4b60 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -23,7 +23,6 @@
# include <cerrno>
#endif
-#include <cstring>
#include <sstream>
using namespace cmFSPermissions;
@@ -715,10 +714,10 @@
}
unsigned long numFiles = dir.GetNumberOfFiles();
for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) {
- if (!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
- strcmp(dir.GetFile(fileNum), "..") == 0)) {
- std::string fromPath = cmStrCat(source, '/', dir.GetFile(fileNum));
- std::string toPath = cmStrCat(destination, '/', dir.GetFile(fileNum));
+ std::string const& file = dir.GetFileName(fileNum);
+ if (file != "." && file != "..") {
+ std::string fromPath = cmStrCat(source, '/', file);
+ std::string toPath = cmStrCat(destination, '/', file);
if (!this->Install(fromPath, toPath)) {
return false;
}
diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx
index ccb7681..1119817 100644
--- a/Source/cmFileSet.cxx
+++ b/Source/cmFileSet.cxx
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmFileSet.h"
-#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
@@ -12,85 +11,21 @@
#include <cmext/algorithm>
#include <cmext/string_view>
-#include "cmsys/RegularExpression.hxx"
-
-#include "cmGenExContext.h"
-#include "cmGeneratorExpression.h"
#include "cmList.h"
#include "cmListFileCache.h"
-#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
+#include "cmTarget.h"
-cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
-{
- switch (vis) {
- case cmFileSetVisibility::Interface:
- return "INTERFACE"_s;
- case cmFileSetVisibility::Public:
- return "PUBLIC"_s;
- case cmFileSetVisibility::Private:
- return "PRIVATE"_s;
- }
- return ""_s;
-}
+namespace Metadata = cm::FileSetMetadata;
-cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
- cmMakefile* mf)
-{
- if (name == "INTERFACE"_s) {
- return cmFileSetVisibility::Interface;
- }
- if (name == "PUBLIC"_s) {
- return cmFileSetVisibility::Public;
- }
- if (name == "PRIVATE"_s) {
- return cmFileSetVisibility::Private;
- }
- auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
- if (mf) {
- mf->IssueMessage(MessageType::FATAL_ERROR, msg);
- } else {
- cmSystemTools::Error(msg);
- }
- return cmFileSetVisibility::Private;
-}
-
-bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
-{
- switch (vis) {
- case cmFileSetVisibility::Interface:
- return false;
- case cmFileSetVisibility::Public:
- case cmFileSetVisibility::Private:
- return true;
- }
- return false;
-}
-
-bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
-{
- switch (vis) {
- case cmFileSetVisibility::Interface:
- case cmFileSetVisibility::Public:
- return true;
- case cmFileSetVisibility::Private:
- return false;
- }
- return false;
-}
-
-bool cmFileSetTypeCanBeIncluded(std::string const& type)
-{
- return type == "HEADERS"_s;
-}
-
-cmFileSet::cmFileSet(cmMakefile* makefile, std::string name, std::string type,
- cmFileSetVisibility visibility)
+cmFileSet::cmFileSet(cmMakefile* makefile, cmTarget* target, std::string name,
+ std::string type, Metadata::Visibility visibility)
: Makefile(makefile)
+ , Target(target)
, Name(std::move(name))
, Type(std::move(type))
, Visibility(visibility)
@@ -123,171 +58,213 @@
this->FileEntries.push_back(std::move(files));
}
-std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
-cmFileSet::CompileFileEntries() const
+cmBTStringRange cmFileSet::GetIncludeDirectories() const
{
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
-
- for (auto const& entry : this->FileEntries) {
- for (auto const& ex : cmList{ entry.Value }) {
- cmGeneratorExpression ge(*this->GetMakefile()->GetCMakeInstance(),
- entry.Backtrace);
- auto cge = ge.Parse(ex);
- result.push_back(std::move(cge));
- }
- }
-
- return result;
+ return cmMakeRange(this->IncludeDirectories);
+}
+cmBTStringRange cmFileSet::GetInterfaceIncludeDirectories() const
+{
+ return cmMakeRange(this->InterfaceIncludeDirectories);
}
-std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
-cmFileSet::CompileDirectoryEntries() const
+cmBTStringRange cmFileSet::GetCompileOptions() const
{
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
-
- for (auto const& entry : this->DirectoryEntries) {
- for (auto const& ex : cmList{ entry.Value }) {
- cmGeneratorExpression ge(*this->GetMakefile()->GetCMakeInstance(),
- entry.Backtrace);
- auto cge = ge.Parse(ex);
- result.push_back(std::move(cge));
- }
- }
-
- return result;
+ return cmMakeRange(this->CompileOptions);
+}
+cmBTStringRange cmFileSet::GetInterfaceCompileOptions() const
+{
+ return cmMakeRange(this->InterfaceCompileOptions);
}
-std::vector<std::string> cmFileSet::EvaluateDirectoryEntries(
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges,
- cm::GenEx::Context const& context, cmGeneratorTarget const* target,
- cmGeneratorExpressionDAGChecker* dagChecker) const
+cmBTStringRange cmFileSet::GetCompileDefinitions() const
{
- struct DirCacheEntry
+ return cmMakeRange(this->CompileDefinitions);
+}
+cmBTStringRange cmFileSet::GetInterfaceCompileDefinitions() const
+{
+ return cmMakeRange(this->InterfaceCompileDefinitions);
+}
+
+namespace {
+enum class ReadOnlyCondition
+{
+ All,
+ Imported,
+ NonImported,
+};
+
+struct ReadOnlyProperty
+{
+ ReadOnlyProperty(ReadOnlyCondition cond)
+ : Condition{ cond }
{
- std::string collapsedDir;
- cm::optional<cmSystemTools::FileId> fileId;
+ }
+ // ReadOnlyProperty(ReadOnlyCondition cond, cmPolicies::PolicyID id)
+ // : Condition{ cond }
+ // , Policy{ id }
+ // {
+ // }
+
+ ReadOnlyCondition Condition;
+ cm::optional<cmPolicies::PolicyID> Policy;
+
+ std::string message(std::string const& prop, cmTarget* target,
+ cmFileSet* fileSet) const
+ {
+ std::string msg;
+ if (this->Condition == ReadOnlyCondition::All) {
+ msg = cmStrCat(" property is read-only for the file set \"",
+ fileSet->GetName(), " of the target \"");
+ } else if (this->Condition == ReadOnlyCondition::Imported) {
+ msg = " property can't be set on a file set attached to the imported "
+ "target \"";
+ } else if (this->Condition == ReadOnlyCondition::NonImported) {
+ msg =
+ " property can't be set on a file set attached to the non-imported "
+ "target \"";
+ }
+ return cmStrCat(prop, msg, target->GetName(), "\"\n");
+ }
+
+ bool isReadOnly(std::string const& prop, cmMakefile* context,
+ cmTarget* target, cmFileSet* fileSet) const
+ {
+ auto importedTarget = target->IsImported();
+ bool matchingCondition = true;
+ if ((!importedTarget && this->Condition == ReadOnlyCondition::Imported) ||
+ (importedTarget &&
+ this->Condition == ReadOnlyCondition::NonImported)) {
+ matchingCondition = false;
+ }
+ if (!matchingCondition) {
+ // Not read-only in this scenario
+ return false;
+ }
+
+ bool readOnly = true;
+ if (!this->Policy) {
+ // No policy associated, so is always read-only
+ context->IssueMessage(MessageType::FATAL_ERROR,
+ this->message(prop, target, fileSet));
+ }
+ return readOnly;
+ }
+};
+
+bool IsSettableProperty(cmMakefile* context, cmTarget* target,
+ cmFileSet* fileSet, std::string const& prop)
+{
+ using ROC = ReadOnlyCondition;
+ static std::unordered_map<std::string, ReadOnlyProperty> const readOnlyProps{
+ { "TYPE", { ROC::All } }, { "SCOPE", { ROC::All } }
};
- std::unordered_map<std::string, DirCacheEntry> dirCache;
- std::vector<std::string> result;
- for (auto const& cge : cges) {
- auto entry = cge->Evaluate(context, dagChecker, target);
- cmList dirs{ entry };
- for (std::string dir : dirs) {
- if (!cmSystemTools::FileIsFullPath(dir)) {
- dir = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', dir);
- }
+ auto it = readOnlyProps.find(prop);
- auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry());
- auto& dirCacheEntry = dirCacheResult.first->second;
- auto const isNewCacheEntry = dirCacheResult.second;
-
- if (isNewCacheEntry) {
- cmSystemTools::FileId fileId;
- auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId);
- dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir);
- dirCacheEntry.fileId =
- isFileIdValid ? cm::optional<decltype(fileId)>(fileId) : cm::nullopt;
- }
-
- for (auto const& priorDir : result) {
- auto priorDirCacheEntry = dirCache.at(priorDir);
- bool sameFile = dirCacheEntry.fileId.has_value() &&
- priorDirCacheEntry.fileId.has_value() &&
- (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId);
- if (!sameFile &&
- (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir,
- priorDirCacheEntry.collapsedDir) ||
- cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir,
- dirCacheEntry.collapsedDir))) {
- context.LG->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(
- "Base directories in file set cannot be subdirectories of each "
- "other:\n ",
- priorDir, "\n ", dir),
- cge->GetBacktrace());
- return {};
- }
- }
- result.push_back(dir);
- }
+ if (it != readOnlyProps.end()) {
+ return !(it->second.isReadOnly(prop, context, target, fileSet));
}
- return result;
+ return true;
}
-void cmFileSet::EvaluateFileEntry(
- std::vector<std::string> const& dirs,
- std::map<std::string, std::vector<std::string>>& filesPerDir,
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
- cm::GenEx::Context const& context, cmGeneratorTarget const* target,
- cmGeneratorExpressionDAGChecker* dagChecker) const
-{
- auto files = cge->Evaluate(context, dagChecker, target);
- for (std::string file : cmList{ files }) {
- if (!cmSystemTools::FileIsFullPath(file)) {
- file = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', file);
- }
- auto collapsedFile = cmSystemTools::CollapseFullPath(file);
- bool found = false;
- std::string relDir;
- for (auto const& dir : dirs) {
- auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
- if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
- found = true;
- relDir = cmSystemTools::GetParentDirectory(
- cmSystemTools::RelativePath(collapsedDir, collapsedFile));
- break;
- }
- }
- if (!found) {
- std::ostringstream e;
- e << "File:\n " << file
- << "\nmust be in one of the file set's base directories:";
- for (auto const& dir : dirs) {
- e << "\n " << dir;
- }
- context.LG->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(), cge->GetBacktrace());
- return;
- }
-
- filesPerDir[relDir].push_back(file);
- }
+cm::string_view const BASE_DIRS = "BASE_DIRS"_s;
+cm::string_view const SOURCES = "SOURCES"_s;
+cm::string_view const INTERFACE_SOURCES = "INTERFACE_SOURCES"_s;
+cm::string_view const INCLUDE_DIRECTORIES = "INCLUDE_DIRECTORIES"_s;
+cm::string_view const INTERFACE_INCLUDE_DIRECTORIES =
+ "INTERFACE_INCLUDE_DIRECTORIES"_s;
+cm::string_view const COMPILE_DEFINITIONS = "COMPILE_DEFINITIONS"_s;
+cm::string_view const INTERFACE_COMPILE_DEFINITIONS =
+ "INTERFACE_COMPILE_DEFINITIONS"_s;
+cm::string_view const COMPILE_OPTIONS = "COMPILE_OPTIONS"_s;
+cm::string_view const INTERFACE_COMPILE_OPTIONS =
+ "INTERFACE_COMPILE_OPTIONS"_s;
}
-bool cmFileSet::IsValidName(std::string const& name)
-{
- static cmsys::RegularExpression const regex("^[a-z0-9][a-zA-Z0-9_]*$");
-
- cmsys::RegularExpressionMatch match;
- return regex.find(name.c_str(), match);
-}
-
-std::string const cmFileSet::propCOMPILE_DEFINITIONS = "COMPILE_DEFINITIONS";
-std::string const cmFileSet::propCOMPILE_OPTIONS = "COMPILE_OPTIONS";
-std::string const cmFileSet::propINCLUDE_DIRECTORIES = "INCLUDE_DIRECTORIES";
-
void cmFileSet::SetProperty(std::string const& prop, cmValue value)
{
- if (prop == propINCLUDE_DIRECTORIES) {
+ if (!IsSettableProperty(this->Makefile, this->Target, this, prop)) {
+ return;
+ }
+
+ if (prop == BASE_DIRS) {
+ this->ClearDirectoryEntries();
+ if (value) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->AddDirectoryEntry(BT<std::string>{ value, lfbt });
+ }
+ } else if (prop == SOURCES) {
+ if (!this->IsForSelf()) {
+ return;
+ }
+ this->ClearFileEntries();
+ if (value) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->AddFileEntry(BT<std::string>{ value, lfbt });
+ }
+ } else if (prop == INTERFACE_SOURCES) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ this->ClearFileEntries();
+ if (value) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->AddFileEntry(BT<std::string>{ value, lfbt });
+ }
+ } else if (prop == INCLUDE_DIRECTORIES) {
+ if (!this->IsForSelf()) {
+ return;
+ }
this->IncludeDirectories.clear();
if (value) {
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
this->IncludeDirectories.emplace_back(value, lfbt);
}
- } else if (prop == propCOMPILE_OPTIONS) {
+ } else if (prop == INTERFACE_INCLUDE_DIRECTORIES) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ this->InterfaceIncludeDirectories.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->InterfaceIncludeDirectories.emplace_back(value, lfbt);
+ }
+ } else if (prop == COMPILE_OPTIONS) {
+ if (!this->IsForSelf()) {
+ return;
+ }
this->CompileOptions.clear();
if (value) {
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
this->CompileOptions.emplace_back(value, lfbt);
}
- } else if (prop == propCOMPILE_DEFINITIONS) {
+ } else if (prop == INTERFACE_COMPILE_OPTIONS) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ this->InterfaceCompileOptions.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->InterfaceCompileOptions.emplace_back(value, lfbt);
+ }
+ } else if (prop == COMPILE_DEFINITIONS) {
+ if (!this->IsForSelf()) {
+ return;
+ }
this->CompileDefinitions.clear();
if (value) {
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
this->CompileDefinitions.emplace_back(value, lfbt);
}
+ } else if (prop == INTERFACE_COMPILE_DEFINITIONS) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ this->InterfaceCompileDefinitions.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->InterfaceCompileDefinitions.emplace_back(value, lfbt);
+ }
} else {
this->Properties.SetProperty(prop, value);
}
@@ -296,21 +273,79 @@
void cmFileSet::AppendProperty(std::string const& prop,
std::string const& value, bool asString)
{
- if (prop == propINCLUDE_DIRECTORIES) {
+ if (!IsSettableProperty(this->Makefile, this->Target, this, prop)) {
+ return;
+ }
+
+ if (prop == BASE_DIRS) {
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->AddDirectoryEntry(BT<std::string>{ value, lfbt });
+ }
+ } else if (prop == SOURCES) {
+ if (!this->IsForSelf()) {
+ return;
+ }
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->AddFileEntry(BT<std::string>{ value, lfbt });
+ }
+ } else if (prop == INTERFACE_SOURCES) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->AddFileEntry(BT<std::string>{ value, lfbt });
+ }
+ } else if (prop == INCLUDE_DIRECTORIES) {
+ if (!this->IsForSelf()) {
+ return;
+ }
if (!value.empty()) {
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
this->IncludeDirectories.emplace_back(value, lfbt);
}
- } else if (prop == propCOMPILE_OPTIONS) {
+ } else if (prop == INTERFACE_INCLUDE_DIRECTORIES) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->InterfaceIncludeDirectories.emplace_back(value, lfbt);
+ }
+ } else if (prop == COMPILE_OPTIONS) {
+ if (!this->IsForSelf()) {
+ return;
+ }
if (!value.empty()) {
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
this->CompileOptions.emplace_back(value, lfbt);
}
- } else if (prop == propCOMPILE_DEFINITIONS) {
+ } else if (prop == INTERFACE_COMPILE_OPTIONS) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->InterfaceCompileOptions.emplace_back(value, lfbt);
+ }
+ } else if (prop == COMPILE_DEFINITIONS) {
+ if (!this->IsForSelf()) {
+ return;
+ }
if (!value.empty()) {
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
this->CompileDefinitions.emplace_back(value, lfbt);
}
+ } else if (prop == INTERFACE_COMPILE_DEFINITIONS) {
+ if (!this->IsForInterface()) {
+ return;
+ }
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
+ this->InterfaceCompileDefinitions.emplace_back(value, lfbt);
+ }
} else {
this->Properties.AppendProperty(prop, value, asString);
}
@@ -319,7 +354,32 @@
cmValue cmFileSet::GetProperty(std::string const& prop) const
{
// Check for the properties with backtraces.
- if (prop == propINCLUDE_DIRECTORIES) {
+ if (prop == BASE_DIRS) {
+
+ static std::string output;
+ output = cmList::to_string(this->GetDirectoryEntries());
+ return cmValue(output);
+ }
+ if (prop == SOURCES) {
+ if (!this->IsForSelf() || this->GetFileEntries().empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmList::to_string(this->GetFileEntries());
+ return cmValue(output);
+ }
+ if (prop == INTERFACE_SOURCES) {
+ if (!this->IsForInterface() || this->GetFileEntries().empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmList::to_string(this->GetFileEntries());
+ return cmValue(output);
+ }
+
+ if (prop == INCLUDE_DIRECTORIES) {
if (this->IncludeDirectories.empty()) {
return nullptr;
}
@@ -329,7 +389,17 @@
return cmValue(output);
}
- if (prop == propCOMPILE_OPTIONS) {
+ if (prop == INTERFACE_INCLUDE_DIRECTORIES) {
+ if (this->InterfaceIncludeDirectories.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmList::to_string(this->InterfaceIncludeDirectories);
+ return cmValue(output);
+ }
+
+ if (prop == COMPILE_OPTIONS) {
if (this->CompileOptions.empty()) {
return nullptr;
}
@@ -339,7 +409,17 @@
return cmValue(output);
}
- if (prop == propCOMPILE_DEFINITIONS) {
+ if (prop == INTERFACE_COMPILE_OPTIONS) {
+ if (this->InterfaceCompileOptions.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmList::to_string(this->InterfaceCompileOptions);
+ return cmValue(output);
+ }
+
+ if (prop == COMPILE_DEFINITIONS) {
if (this->CompileDefinitions.empty()) {
return nullptr;
}
@@ -349,5 +429,24 @@
return cmValue(output);
}
+ if (prop == INTERFACE_COMPILE_DEFINITIONS) {
+ if (this->InterfaceCompileDefinitions.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmList::to_string(this->InterfaceCompileDefinitions);
+ return cmValue(output);
+ }
+
+ if (prop == "TYPE"_s) {
+ return cmValue{ this->GetType() };
+ }
+ if (prop == "SCOPE"_s) {
+ static std::string scope =
+ std::string{ Metadata::VisibilityToName(this->GetVisibility()) };
+ return cmValue{ scope };
+ }
+
return this->Properties.GetPropertyValue(prop);
}
diff --git a/Source/cmFileSet.h b/Source/cmFileSet.h
index 598e832..eb5e9e3 100644
--- a/Source/cmFileSet.h
+++ b/Source/cmFileSet.h
@@ -3,55 +3,49 @@
#pragma once
#include <cstddef>
-#include <map>
-#include <memory>
#include <string>
#include <vector>
#include <cm/string_view>
-#include <cmext/string_view>
+#include "cmAlgorithms.h"
+#include "cmFileSetMetadata.h"
#include "cmListFileCache.h"
#include "cmPropertyMap.h"
#include "cmValue.h"
-namespace cm {
-namespace GenEx {
-struct Context;
-}
-}
-
-class cmCompiledGeneratorExpression;
-struct cmGeneratorExpressionDAGChecker;
-class cmGeneratorTarget;
class cmMakefile;
-
-enum class cmFileSetVisibility
-{
- Private,
- Public,
- Interface,
-};
-cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis);
-cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
- cmMakefile* mf);
-bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis);
-bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis);
-
-bool cmFileSetTypeCanBeIncluded(std::string const& type);
+class cmTarget;
class cmFileSet
{
public:
- cmFileSet(cmMakefile* makefile, std::string name, std::string type,
- cmFileSetVisibility visibility);
+ cmFileSet(cmMakefile* makefile, cmTarget* target, std::string name,
+ std::string type, cm::FileSetMetadata::Visibility visibility);
std::string const& GetName() const { return this->Name; }
std::string const& GetType() const { return this->Type; }
- cmFileSetVisibility GetVisibility() const { return this->Visibility; }
+ cm::FileSetMetadata::Visibility GetVisibility() const
+ {
+ return this->Visibility;
+ }
cmMakefile* GetMakefile() const { return this->Makefile; }
+ bool IsForSelf() const
+ {
+ return cm::FileSetMetadata::VisibilityIsForSelf(this->GetVisibility());
+ }
+ bool IsForInterface() const
+ {
+ return cm::FileSetMetadata::VisibilityIsForInterface(
+ this->GetVisibility());
+ }
+ bool CanBeIncluded() const
+ {
+ return this->Type != cm::FileSetMetadata::CXX_MODULES;
+ }
+
void CopyEntries(cmFileSet const* fs);
void ClearDirectoryEntries();
@@ -68,25 +62,15 @@
return this->FileEntries;
}
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
- CompileFileEntries() const;
+ // Special properties
+ cmBTStringRange GetIncludeDirectories() const;
+ cmBTStringRange GetInterfaceIncludeDirectories() const;
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
- CompileDirectoryEntries() const;
+ cmBTStringRange GetCompileOptions() const;
+ cmBTStringRange GetInterfaceCompileOptions() const;
- std::vector<std::string> EvaluateDirectoryEntries(
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges,
- cm::GenEx::Context const& context, cmGeneratorTarget const* target,
- cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
-
- void EvaluateFileEntry(
- std::vector<std::string> const& dirs,
- std::map<std::string, std::vector<std::string>>& filesPerDir,
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
- cm::GenEx::Context const& context, cmGeneratorTarget const* target,
- cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
-
- static bool IsValidName(std::string const& name);
+ cmBTStringRange GetCompileDefinitions() const;
+ cmBTStringRange GetInterfaceCompileDefinitions() const;
//! Set/Get a property of this file set
void SetProperty(std::string const& prop, cmValue value);
@@ -108,17 +92,17 @@
private:
cmMakefile* Makefile;
+ cmTarget* Target;
std::string Name;
std::string Type;
- cmFileSetVisibility Visibility;
+ cm::FileSetMetadata::Visibility Visibility;
std::vector<BT<std::string>> DirectoryEntries;
std::vector<BT<std::string>> FileEntries;
cmPropertyMap Properties;
- std::vector<BT<std::string>> CompileOptions;
- std::vector<BT<std::string>> CompileDefinitions;
std::vector<BT<std::string>> IncludeDirectories;
-
- static std::string const propCOMPILE_DEFINITIONS;
- static std::string const propCOMPILE_OPTIONS;
- static std::string const propINCLUDE_DIRECTORIES;
+ std::vector<BT<std::string>> InterfaceIncludeDirectories;
+ std::vector<BT<std::string>> CompileOptions;
+ std::vector<BT<std::string>> InterfaceCompileOptions;
+ std::vector<BT<std::string>> CompileDefinitions;
+ std::vector<BT<std::string>> InterfaceCompileDefinitions;
};
diff --git a/Source/cmFileSetMetadata.cxx b/Source/cmFileSetMetadata.cxx
new file mode 100644
index 0000000..821a969
--- /dev/null
+++ b/Source/cmFileSetMetadata.cxx
@@ -0,0 +1,166 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmFileSetMetadata.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include <cmext/algorithm>
+#include <cmext/string_view>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+namespace cm {
+namespace FileSetMetadata {
+cm::string_view VisibilityToName(Visibility vis)
+{
+ switch (vis) {
+ case Visibility::Interface:
+ return "INTERFACE"_s;
+ case Visibility::Public:
+ return "PUBLIC"_s;
+ case Visibility::Private:
+ return "PRIVATE"_s;
+ }
+ return ""_s;
+}
+
+Visibility VisibilityFromName(cm::string_view name, cmMakefile* mf)
+{
+ if (name == "INTERFACE"_s) {
+ return Visibility::Interface;
+ }
+ if (name == "PUBLIC"_s) {
+ return Visibility::Public;
+ }
+ if (name == "PRIVATE"_s) {
+ return Visibility::Private;
+ }
+ auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
+ if (mf) {
+ mf->IssueMessage(MessageType::FATAL_ERROR, msg);
+ } else {
+ cmSystemTools::Error(msg);
+ }
+ return Visibility::Private;
+}
+
+bool VisibilityIsForSelf(Visibility vis)
+{
+ switch (vis) {
+ case Visibility::Interface:
+ return false;
+ case Visibility::Public:
+ case Visibility::Private:
+ return true;
+ }
+ return false;
+}
+
+bool VisibilityIsForInterface(Visibility vis)
+{
+ switch (vis) {
+ case Visibility::Interface:
+ case Visibility::Public:
+ return true;
+ case Visibility::Private:
+ return false;
+ }
+ return false;
+}
+
+cm::string_view const HEADERS = "HEADERS"_s;
+cm::string_view const SOURCES = "SOURCES"_s;
+cm::string_view const CXX_MODULES = "CXX_MODULES"_s;
+
+namespace {
+std::map<cm::string_view, FileSetDescriptor> const FileSetDescriptors{
+ { cm::FileSetMetadata::HEADERS,
+ { cm::FileSetMetadata::HEADERS,
+ cm::FileSetMetadata::FileSetLookup::Target,
+ { DependencyMode ::Includables },
+ DependencyMode ::Includables,
+ FrameworkCompatible::No } },
+ { cm::FileSetMetadata::SOURCES,
+ { cm::FileSetMetadata::SOURCES,
+ cm::FileSetMetadata::FileSetLookup::Dependencies,
+ { DependencyMode ::IndependentFiles, DependencyMode ::Includables },
+ DependencyMode ::Includables,
+ FrameworkCompatible::Yes } },
+ { cm::FileSetMetadata::CXX_MODULES,
+ { cm::FileSetMetadata::CXX_MODULES,
+ cm::FileSetMetadata::FileSetLookup::Target,
+ { DependencyMode ::IndependentFiles },
+ DependencyMode ::IndependentFiles,
+ FrameworkCompatible::No } },
+};
+
+std::vector<cm::string_view> KnownTypes{ HEADERS, SOURCES, CXX_MODULES };
+
+cmsys::RegularExpression const ValidNameRegex("^[a-z0-9][a-zA-Z0-9_]*$");
+}
+
+cm::optional<FileSetDescriptor> GetFileSetDescriptor(cm::string_view type)
+{
+ auto it = FileSetDescriptors.find(type);
+ if (it != FileSetDescriptors.end()) {
+ return it->second;
+ }
+ return cm::nullopt;
+}
+
+DependencyMode GetDependencyMode(cm::string_view type)
+{
+ auto descriptor = GetFileSetDescriptor(type);
+ if (descriptor) {
+ return descriptor->DefaultDependency;
+ }
+ return DependencyMode::Includables;
+}
+DependencyMode GetDependencyMode(cm::string_view type,
+ DependencyMode requestedMode)
+{
+ auto descriptor = GetFileSetDescriptor(type);
+ if (descriptor) {
+ // Select the requested mode or the next-weakest mode that is supported by
+ // the file set type
+ auto mode = descriptor->SupportedDependencies.lower_bound(requestedMode);
+ return mode == descriptor->SupportedDependencies.end()
+ ? descriptor->DefaultDependency
+ : *mode;
+ }
+ return DependencyMode::Includables;
+}
+
+bool IsFrameworkSupported(cm::string_view type)
+{
+ auto descriptor = GetFileSetDescriptor(type);
+ if (descriptor) {
+ return descriptor->FrameworkSupported == FrameworkCompatible::Yes;
+ }
+ return false;
+}
+
+std::vector<cm::string_view> const& GetKnownTypes()
+{
+ return KnownTypes;
+}
+
+bool IsKnownType(cm::string_view type)
+{
+ return cm::contains(GetKnownTypes(), type);
+}
+
+bool IsValidName(cm::string_view name)
+{
+ cmsys::RegularExpressionMatch match;
+ return ValidNameRegex.find(name.data(), match);
+}
+}
+}
diff --git a/Source/cmFileSetMetadata.h b/Source/cmFileSetMetadata.h
new file mode 100644
index 0000000..9a28dd2
--- /dev/null
+++ b/Source/cmFileSetMetadata.h
@@ -0,0 +1,103 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+#include <cm/string_view>
+
+class cmMakefile;
+
+namespace cm {
+namespace FileSetMetadata {
+enum class Visibility
+{
+ Private,
+ Public,
+ Interface
+};
+
+cm::string_view VisibilityToName(Visibility vis);
+Visibility VisibilityFromName(cm::string_view name, cmMakefile* mf);
+
+bool VisibilityIsForSelf(Visibility vis);
+bool VisibilityIsForInterface(Visibility vis);
+
+// Pre-defined FileSet types
+extern cm::string_view const HEADERS;
+extern cm::string_view const SOURCES;
+extern cm::string_view const CXX_MODULES;
+
+enum class FileSetLookup
+{
+ // Search for file sets attached to the target
+ Target,
+ // Search also file sets inherited from link libraries
+ Dependencies
+};
+
+// Define the various modes regarding graph dependency for
+// the generated files (Ninja specific)
+// items must be kept in this order: "Lower" modes are "stronger" in that they
+// have more restrictions (and therefore allow for more build graph
+// optimization).
+// std::set rely on it.
+enum class DependencyMode
+{
+ IndependentFiles, // files in the file set are independent from each other
+ Includables, // files can be used by another source during compilation
+};
+using DependencySet = std::set<DependencyMode>;
+
+enum class FrameworkCompatible
+{
+ No,
+ Yes
+};
+
+struct FileSetDescriptor
+{
+ FileSetDescriptor(cm::string_view type, FileSetLookup lookup,
+ DependencySet dependencies,
+ DependencyMode defaultDependency,
+ FrameworkCompatible frameworkSupported)
+ : Type(type)
+ , Lookup(lookup)
+ , SupportedDependencies(std::move(dependencies))
+ , DefaultDependency(defaultDependency)
+ , FrameworkSupported(frameworkSupported)
+ {
+ }
+
+ FileSetDescriptor(FileSetLookup lookup)
+ : Type()
+ , Lookup(lookup)
+ , SupportedDependencies({ DependencyMode::Includables })
+ , DefaultDependency(DependencyMode::Includables)
+ , FrameworkSupported(FrameworkCompatible::No)
+ {
+ }
+
+ cm::string_view const Type;
+ FileSetLookup const Lookup;
+ DependencySet const SupportedDependencies;
+ DependencyMode const DefaultDependency;
+ FrameworkCompatible const FrameworkSupported;
+};
+
+cm::optional<FileSetDescriptor> GetFileSetDescriptor(cm::string_view type);
+DependencyMode GetDependencyMode(cm::string_view type);
+DependencyMode GetDependencyMode(cm::string_view type,
+ DependencyMode requestedMode);
+bool IsFrameworkSupported(cm::string_view type);
+
+std::vector<cm::string_view> const& GetKnownTypes();
+bool IsKnownType(cm::string_view type);
+
+// check validity of a user's file set name
+bool IsValidName(cm::string_view type);
+}
+}
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index f0d784a..e3e1ba7 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -113,12 +113,10 @@
};
#endif
-bool isDirentryToIgnore(char const* const fname)
+bool isDirentryToIgnore(std::string const& fname)
{
- assert(fname);
- assert(fname[0] != 0);
- return fname[0] == '.' &&
- (fname[1] == 0 || (fname[1] == '.' && fname[2] == 0));
+ assert(!fname.empty());
+ return fname == "." || fname == "..";
}
class cmAppendPathSegmentGenerator
@@ -188,12 +186,12 @@
}
while (this->CurrentIdx < this->DirectoryLister.GetNumberOfFiles()) {
- char const* const fname =
- this->DirectoryLister.GetFile(this->CurrentIdx++);
+ std::string const& fname =
+ this->DirectoryLister.GetFileName(this->CurrentIdx++);
if (isDirentryToIgnore(fname)) {
continue;
}
- if (cmsysString_strcasecmp(fname, this->DirName.data()) == 0) {
+ if (cmsysString_strcasecmp(fname.c_str(), this->DirName.data()) == 0) {
auto candidate = cmStrCat(parent, fname, '/');
if (cmSystemTools::FileIsDirectory(candidate)) {
return candidate;
@@ -243,7 +241,7 @@
// TODO If so, just start with index 2 and drop the
// `isDirentryToIgnore(i)` condition to check.
for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) {
- char const* const fname = directoryLister.GetFile(i);
+ std::string const& fname = directoryLister.GetFileName(i);
// Skip entries to ignore or that aren't directories.
if (isDirentryToIgnore(fname)) {
continue;
@@ -261,8 +259,8 @@
// Skip entries that don't match.
auto const equal =
((this->ExactMatch
- ? cmsysString_strcasecmp(fname, name.c_str())
- : cmsysString_strncasecmp(fname, name.c_str(),
+ ? cmsysString_strcasecmp(fname.c_str(), name.c_str())
+ : cmsysString_strncasecmp(fname.c_str(), name.c_str(),
name.length())) == 0);
if (equal) {
if (directoryLister.FileIsDirectory(i)) {
@@ -1585,7 +1583,7 @@
found = true;
std::string const var = cmStrCat(this->Name, "_FIND_MODULE");
this->Makefile->AddDefinition(var, "1");
- bool result = this->ReadListFile(mfile, DoPolicyScope);
+ bool result = this->ReadListFile(mfile, cm::PolicyScope::Local);
this->Makefile->RemoveDefinition(var);
std::string const foundVar = cmStrCat(this->Name, "_FOUND");
@@ -1703,7 +1701,7 @@
// The package has been found.
found = true;
result = this->ReadPackage();
- } else if (this->ReadListFile(this->FileFound, DoPolicyScope)) {
+ } else if (this->ReadListFile(this->FileFound, cm::PolicyScope::Local)) {
// The package has been found.
found = true;
@@ -2075,9 +2073,11 @@
}
bool cmFindPackageCommand::ReadListFile(std::string const& f,
- PolicyScopeRule const psr)
+ cm::PolicyScope ps)
{
- bool const noPolicyScope = !this->PolicyScope || psr == NoPolicyScope;
+ if (!this->PolicyScope) {
+ ps = cm::PolicyScope::None;
+ }
using ITScope = cmMakefile::ImportedTargetScope;
ITScope scope = this->GlobalScope ? ITScope::Global : ITScope::Local;
@@ -2088,7 +2088,8 @@
// This allows child snapshots to inherit the CAN_UNWIND state from us, we'll
// reset it immediately after the dependent file is done
this->Makefile->GetStateSnapshot().SetUnwindType(cmStateEnums::CAN_UNWIND);
- bool result = this->Makefile->ReadDependentFile(f, noPolicyScope);
+ bool const result =
+ this->Makefile->ReadDependentFile(f, ps, cm::DiagnosticScope::Local);
this->Makefile->GetStateSnapshot().SetUnwindType(oldUnwind);
this->Makefile->GetStateSnapshot().SetUnwindState(
@@ -2726,7 +2727,7 @@
std::string fname;
for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) {
- fname = cmStrCat(dir, '/', files.GetFile(i));
+ fname = cmStrCat(dir, '/', files.GetFileName(i));
if (!cmSystemTools::FileIsDirectory(fname)) {
// Hold this file hostage until it behaves.
@@ -3209,7 +3210,7 @@
// Load the version check file.
// Pass NoPolicyScope because we do our own policy push/pop.
bool suitable = false;
- if (this->ReadListFile(version_file, NoPolicyScope)) {
+ if (this->ReadListFile(version_file, cm::PolicyScope::None)) {
// Check the output variables.
bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT");
bool const unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE");
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 740cdca..7c71666 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -32,6 +32,10 @@
/* clang-format on */
#endif
+namespace cm {
+enum class PolicyScope : bool;
+}
+
class cmExecutionStatus;
class cmPackageState;
class cmSearchPath;
@@ -139,12 +143,7 @@
bool FindFrameworkConfig();
bool FindAppBundleConfig();
bool FindEnvironmentConfig();
- enum PolicyScopeRule
- {
- NoPolicyScope,
- DoPolicyScope
- };
- bool ReadListFile(std::string const& f, PolicyScopeRule psr);
+ bool ReadListFile(std::string const& f, cm::PolicyScope ps);
bool ReadPackage();
struct Appendix
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index a629438..60c3b90 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -10,6 +10,7 @@
#include <cmext/algorithm>
#include <cmext/string_view>
+#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
#include "cmList.h"
@@ -47,6 +48,7 @@
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
cmPolicies::PolicyMap Policies;
+ cmDiagnostics::DiagnosticMap Diagnostics;
std::string FilePath;
long Line;
};
@@ -72,7 +74,7 @@
}
cmMakefile::FunctionPushPop functionScope(&makefile, this->FilePath,
- this->Policies);
+ this->Policies, this->Diagnostics);
// set the value of argc
makefile.AddDefinition(ARGC, std::to_string(expandedArgs.size()));
@@ -171,6 +173,7 @@
f.FilePath = this->GetStartingContext().FilePath;
f.Line = this->GetStartingContext().Line;
mf.RecordPolicies(f.Policies);
+ mf.RecordDiagnostics(f.Diagnostics);
return mf.GetState()->AddScriptedCommand(
this->Args.front(),
BT<cmState::Command>(std::move(f),
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index b938329..bb4f0bc 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -29,12 +29,12 @@
#include "cmCMakePath.h"
#include "cmCMakeString.hxx"
#include "cmComputeLinkInformation.h"
-#include "cmFileSet.h"
#include "cmGenExContext.h"
#include "cmGenExEvaluation.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionEvaluator.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
@@ -3582,11 +3582,12 @@
namespace {
bool GetFileSet(std::vector<std::string> const& parameters,
cm::GenEx::Evaluation* eval,
- GeneratorExpressionContent const* content, cmFileSet*& fileSet)
+ GeneratorExpressionContent const* content,
+ cmGeneratorTarget const*& target,
+ cmGeneratorFileSet const*& fileSet)
{
auto const& fileSetName = parameters[0];
auto targetName = parameters[1];
- auto* makefile = eval->Context.LG->GetMakefile();
fileSet = nullptr;
auto const TARGET = "TARGET:"_s;
@@ -3598,7 +3599,11 @@
cmStrCat("No value provided for the ", TARGET, " option."));
return false;
}
- auto* target = makefile->FindTargetToUse(targetName);
+
+ cmLocalGenerator const* lg = eval->CurrentTarget
+ ? eval->CurrentTarget->GetLocalGenerator()
+ : eval->Context.LG;
+ target = lg->FindGeneratorTargetToUse(targetName);
if (!target) {
reportError(eval, content->GetOriginalExpression(),
cmStrCat("Non-existent target: ", targetName));
@@ -3634,8 +3639,9 @@
return std::string{};
}
- cmFileSet* fileSet = nullptr;
- if (!GetFileSet(parameters, eval, content, fileSet)) {
+ cmGeneratorTarget const* target = nullptr;
+ cmGeneratorFileSet const* fileSet = nullptr;
+ if (!GetFileSet(parameters, eval, content, target, fileSet)) {
return std::string{};
}
@@ -3653,7 +3659,7 @@
std::string Evaluate(
std::vector<std::string> const& parameters, cm::GenEx::Evaluation* eval,
GeneratorExpressionContent const* content,
- cmGeneratorExpressionDAGChecker* /*dagCheckerParent*/) const override
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
{
static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
@@ -3686,8 +3692,9 @@
return std::string{};
}
- cmFileSet* fileSet = nullptr;
- if (!GetFileSet(parameters, eval, content, fileSet)) {
+ cmGeneratorTarget const* target = nullptr;
+ cmGeneratorFileSet const* fileSet = nullptr;
+ if (!GetFileSet(parameters, eval, content, target, fileSet)) {
return std::string{};
}
if (!fileSet) {
@@ -3697,7 +3704,32 @@
return std::string{};
}
- return fileSet->GetProperty(propertyName);
+ auto result = fileSet->GetProperty(propertyName);
+
+ if (propertyName == "BASE_DIRS"_s || propertyName == "SOURCES"_s ||
+ propertyName == "INTERFACE_SOURCES"_s) {
+ cmGeneratorExpressionDAGChecker dagChecker{
+ target, propertyName, content,
+ dagCheckerParent, eval->Context, eval->Backtrace,
+ };
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ dagChecker.ReportError(eval, content->GetOriginalExpression());
+ return std::string{};
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ return std::string{};
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ return cmGeneratorExpression::StripEmptyListElements(
+ this->EvaluateDependentExpression(result, eval, target, &dagChecker,
+ target));
+ }
+
+ return result;
}
} fileSetPropertyNode;
@@ -4303,6 +4335,55 @@
return std::string();
}
+ std::vector<std::string> sourceFilePaths;
+ for (auto const& arg : cmMakeRange(parameters).advance(1)) {
+ if (cmHasLiteralPrefix(arg, "SOURCE_FILES:")) {
+ cm::string_view listView{ arg.c_str() + cmStrLen("SOURCE_FILES:") };
+ std::size_t semicolon;
+ std::size_t start = 0;
+ do {
+ semicolon = listView.find(';', start);
+ sourceFilePaths.push_back(
+ std::string{ listView.substr(start, semicolon - start) });
+ start = semicolon + 1;
+ } while (semicolon != cm::string_view::npos);
+ } else {
+ reportError(eval, content->GetOriginalExpression(),
+ cmStrCat("Unrecognized argument:\n ", arg));
+ return std::string();
+ }
+ }
+
+ if (gt->IsImported() && !sourceFilePaths.empty()) {
+ reportError(
+ eval, content->GetOriginalExpression(),
+ cmStrCat("Cannot use SOURCE_FILES argument on imported target \"",
+ tgtName, '"'));
+ return std::string();
+ }
+ std::set<cmSourceFile const*> sourceFiles;
+ for (auto const& sf : gt->GetSourceFiles(eval->Context.Config)) {
+ sourceFiles.insert(sf.Value);
+ }
+ std::set<cmSourceFile const*> filteredSourceFiles;
+ for (auto const& path : sourceFilePaths) {
+ if (!cmSystemTools::FileIsFullPath(path)) {
+ reportError(
+ eval, content->GetOriginalExpression(),
+ cmStrCat("Source file:\n ", path, "\nis not an absolute path"));
+ return std::string();
+ }
+
+ auto const* sf = gt->Makefile->GetSource(path);
+ if (!sf || !sourceFiles.count(sf)) {
+ reportError(eval, content->GetOriginalExpression(),
+ cmStrCat("Source file:\n ", path,
+ "\ndoes not exist for target \"", tgtName, '"'));
+ return std::string();
+ }
+ filteredSourceFiles.insert(sf);
+ }
+
cmList objects;
if (gt->IsImported()) {
@@ -4315,7 +4396,11 @@
}
eval->HadContextSensitiveCondition = true;
} else {
- gt->GetTargetObjectNames(eval->Context.Config, objects);
+ auto const filter =
+ [&filteredSourceFiles](cmSourceFile const& sf) -> bool {
+ return filteredSourceFiles.empty() || filteredSourceFiles.count(&sf);
+ };
+ gt->GetTargetObjectNames(eval->Context.Config, filter, objects);
std::string obj_dir;
if (eval->EvaluateForBuildsystem && !gg->SupportsCrossConfigs()) {
@@ -4341,6 +4426,8 @@
return objects.to_string();
}
+
+ int NumExpectedParameters() const override { return OneOrMoreParameters; }
} targetObjectsNode;
struct TargetRuntimeDllsBaseNode : public cmGeneratorExpressionNode
diff --git a/Source/cmGeneratorFileSet.cxx b/Source/cmGeneratorFileSet.cxx
new file mode 100644
index 0000000..c2505f5
--- /dev/null
+++ b/Source/cmGeneratorFileSet.cxx
@@ -0,0 +1,598 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmGeneratorFileSet.h"
+
+#include <algorithm>
+#include <map>
+#include <sstream>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmAlgorithms.h"
+#include "cmEvaluatedTargetProperty.h"
+#include "cmFileSet.h"
+#include "cmGenExContext.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorTarget.h"
+#include "cmList.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+class cmLinkItem;
+
+namespace {
+class FileSetPropertyEntry : public cm::TargetPropertyEntry
+{
+public:
+ FileSetPropertyEntry(
+ std::vector<std::string> dirs, bool contextSensitiveDirs,
+ std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
+ cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem)
+ : cm::TargetPropertyEntry(item)
+ , BaseDirs(std::move(dirs))
+ , ContextSensitiveDirs(contextSensitiveDirs)
+ , Cge(cge)
+ , FileSet(fileSet)
+ {
+ }
+
+ static std::unique_ptr<cm::TargetPropertyEntry> CreateFileSetEntry(
+ std::vector<std::string> dirs, bool contextSensitiveDirs,
+ std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
+ cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem)
+ {
+ return cm::make_unique<FileSetPropertyEntry>(
+ std::move(dirs), contextSensitiveDirs, cge, fileSet, item);
+ }
+
+ std::string const& Evaluate(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ std::map<std::string, std::vector<std::string>> filesPerDir;
+ this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir, this->Cge,
+ context, headTarget, dagChecker);
+
+ std::vector<std::string> files;
+ for (auto const& it : filesPerDir) {
+ files.insert(files.end(), it.second.begin(), it.second.end());
+ }
+
+ this->Value = cmList::to_string(files);
+ return Value;
+ }
+
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->Cge->GetBacktrace();
+ }
+
+ std::string const& GetInput() const override
+ {
+ return this->Cge->GetInput();
+ }
+
+ bool GetHadContextSensitiveCondition() const override
+ {
+ return this->ContextSensitiveDirs ||
+ this->Cge->GetHadContextSensitiveCondition();
+ }
+
+private:
+ std::vector<std::string> const BaseDirs;
+ bool const ContextSensitiveDirs;
+ std::unique_ptr<cmCompiledGeneratorExpression> const& Cge;
+ cmGeneratorFileSet const* FileSet;
+ mutable std::string Value;
+};
+
+void CreatePropertyGeneratorExpressions(
+ cmake& cmakeInstance, cmBTStringRange entries,
+ std::vector<std::unique_ptr<cm::TargetPropertyEntry>>& items)
+{
+ for (auto const& entry : entries) {
+ items.emplace_back(
+ cm::TargetPropertyEntry::Create(cmakeInstance, entry, false));
+ }
+}
+
+enum class OptionsParse
+{
+ None,
+ Shell
+};
+
+std::vector<BT<std::string>> ProcessOptions(
+ cm::EvaluatedTargetPropertyEntries const& entries,
+ OptionsParse parse = OptionsParse::None)
+{
+ std::vector<BT<std::string>> options;
+ std::unordered_set<std::string> uniqueOptions;
+
+ for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
+ for (std::string const& opt : entry.Values) {
+ if (uniqueOptions.insert(opt).second) {
+ if (parse == OptionsParse::Shell &&
+ cmHasLiteralPrefix(opt, "SHELL:")) {
+ std::vector<std::string> tmp;
+ cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
+ for (std::string& o : tmp) {
+ options.emplace_back(std::move(o), entry.Backtrace);
+ }
+ } else {
+ options.emplace_back(opt, entry.Backtrace);
+ }
+ }
+ }
+ }
+ return options;
+}
+std::vector<BT<std::string>> ProcessIncludes(
+ cmGeneratorTarget const* target, std::string const& fileSetName,
+ cm::string_view property, cm::EvaluatedTargetPropertyEntries& entries)
+{
+ std::vector<BT<std::string>> includes;
+ std::unordered_set<std::string> uniqueIncludes;
+
+ for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
+ for (std::string& include : entry.Values) {
+ if (!cmValue::IsOff(include)) {
+ cmSystemTools::ConvertToUnixSlashes(include);
+ }
+
+ if (!cmSystemTools::FileIsFullPath(include)) {
+ target->GetLocalGenerator()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("File set \"", fileSetName, "\" from the target \"",
+ target->GetName(), "\" contains relative path in its ",
+ property, ":\n \"", include, "\""));
+ return includes;
+ }
+
+ if (uniqueIncludes.insert(include).second) {
+ includes.emplace_back(include, entry.Backtrace);
+ }
+ }
+ }
+ return includes;
+}
+}
+
+//
+// Class cmGeneratorFileSet
+//
+cmGeneratorFileSet::cmGeneratorFileSet(cmGeneratorTarget const* target,
+ cmFileSet const* fileSet)
+ : Target(target)
+ , FileSet(fileSet)
+{
+ auto& cmake = *target->GetLocalGenerator()->GetCMakeInstance();
+
+ CreatePropertyGeneratorExpressions(cmake, fileSet->GetIncludeDirectories(),
+ this->IncludeDirectories);
+ CreatePropertyGeneratorExpressions(cmake,
+ fileSet->GetInterfaceIncludeDirectories(),
+ this->InterfaceIncludeDirectories);
+
+ CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileOptions(),
+ this->CompileOptions);
+ CreatePropertyGeneratorExpressions(cmake,
+ fileSet->GetInterfaceCompileOptions(),
+ this->InterfaceCompileOptions);
+
+ CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileDefinitions(),
+ this->CompileDefinitions);
+ CreatePropertyGeneratorExpressions(cmake,
+ fileSet->GetInterfaceCompileDefinitions(),
+ this->InterfaceCompileDefinitions);
+}
+
+std::string const& cmGeneratorFileSet::GetName() const
+{
+ return this->FileSet->GetName();
+}
+std::string const& cmGeneratorFileSet::GetType() const
+{
+ return this->FileSet->GetType();
+}
+cm::FileSetMetadata::Visibility cmGeneratorFileSet::GetVisibility() const
+{
+ return this->FileSet->GetVisibility();
+}
+
+bool cmGeneratorFileSet::IsForSelf() const
+{
+ return this->FileSet->IsForSelf();
+}
+bool cmGeneratorFileSet::IsForInterface() const
+{
+ return this->FileSet->IsForInterface();
+}
+bool cmGeneratorFileSet::CanBeIncluded() const
+{
+ return this->FileSet->CanBeIncluded();
+}
+
+cmValue cmGeneratorFileSet::GetProperty(std::string const& prop) const
+{
+ return this->FileSet->GetProperty(prop);
+}
+
+std::vector<BT<std::string>> cmGeneratorFileSet::GetIncludeDirectories(
+ std::string const& config, std::string const& lang) const
+{
+ ConfigAndLanguage cacheKey(config, lang);
+ {
+ auto it = this->IncludeDirectoriesCache.find(cacheKey);
+ if (it != this->IncludeDirectoriesCache.end()) {
+ return it->second;
+ }
+ }
+
+ cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang);
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
+ this->IncludeDirectories);
+ auto includes = ProcessIncludes(this->Target, this->GetName(),
+ "INCLUDE_DIRECTORIES"_s, entries);
+ this->IncludeDirectoriesCache.emplace(cacheKey, includes);
+
+ return includes;
+}
+std::vector<BT<std::string>>
+cmGeneratorFileSet::GetInterfaceIncludeDirectories(
+ std::string const& config, std::string const& lang) const
+{
+ ConfigAndLanguage cacheKey(config, lang);
+ {
+ auto it = this->InterfaceIncludeDirectoriesCache.find(cacheKey);
+ if (it != this->InterfaceIncludeDirectoriesCache.end()) {
+ return it->second;
+ }
+ }
+
+ cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang);
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
+ this->InterfaceIncludeDirectories);
+ auto includes = ProcessIncludes(this->Target, this->GetName(),
+ "INTERFACE_INCLUDE_DIRECTORIES"_s, entries);
+ this->InterfaceIncludeDirectoriesCache.emplace(cacheKey, includes);
+
+ return includes;
+}
+
+std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileOptions(
+ std::string const& config, std::string const& language) const
+{
+ ConfigAndLanguage cacheKey(config, language);
+ {
+ auto it = this->CompileOptionsCache.find(cacheKey);
+ if (it != this->CompileOptionsCache.end()) {
+ return it->second;
+ }
+ }
+
+ cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
+ language);
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
+ this->CompileOptions);
+ auto options = ProcessOptions(entries, OptionsParse::Shell);
+ this->CompileOptionsCache.emplace(cacheKey, options);
+
+ return options;
+}
+std::vector<BT<std::string>> cmGeneratorFileSet::GetInterfaceCompileOptions(
+ std::string const& config, std::string const& language) const
+{
+ ConfigAndLanguage cacheKey(config, language);
+ {
+ auto it = this->InterfaceCompileOptionsCache.find(cacheKey);
+ if (it != this->InterfaceCompileOptionsCache.end()) {
+ return it->second;
+ }
+ }
+
+ cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
+ language);
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
+ this->InterfaceCompileOptions);
+ auto options = ProcessOptions(entries, OptionsParse::Shell);
+ this->InterfaceCompileOptionsCache.emplace(cacheKey, options);
+
+ return options;
+}
+
+std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileDefinitions(
+ std::string const& config, std::string const& language) const
+{
+ ConfigAndLanguage cacheKey(config, language);
+ {
+ auto it = this->CompileDefinitionsCache.find(cacheKey);
+ if (it != this->CompileDefinitionsCache.end()) {
+ return it->second;
+ }
+ }
+
+ cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
+ language);
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
+ this->CompileDefinitions);
+ auto defines = ProcessOptions(entries);
+ this->CompileDefinitionsCache.emplace(cacheKey, defines);
+
+ return defines;
+}
+std::vector<BT<std::string>>
+cmGeneratorFileSet::GetInterfaceCompileDefinitions(
+ std::string const& config, std::string const& language) const
+{
+ ConfigAndLanguage cacheKey(config, language);
+ {
+ auto it = this->InterfaceCompileDefinitionsCache.find(cacheKey);
+ if (it != this->InterfaceCompileDefinitionsCache.end()) {
+ return it->second;
+ }
+ }
+
+ cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
+ language);
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
+ this->InterfaceCompileDefinitions);
+ auto defines = ProcessOptions(entries);
+ this->InterfaceCompileDefinitionsCache.emplace(cacheKey, defines);
+
+ return defines;
+}
+
+std::vector<BT<std::string>> const& cmGeneratorFileSet::GetDirectoryEntries()
+ const
+{
+ return this->FileSet->GetDirectoryEntries();
+}
+
+std::vector<BT<std::string>> const& cmGeneratorFileSet::GetFileEntries() const
+{
+ return this->FileSet->GetFileEntries();
+}
+
+std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const&
+cmGeneratorFileSet::CompileFileEntries() const
+{
+ std::unordered_set<std::string> uniqueSrcs;
+
+ if (this->CompiledFileEntries.empty() &&
+ !this->FileSet->GetFileEntries().empty()) {
+ for (auto const& entry : this->FileSet->GetFileEntries()) {
+ for (auto const& ex : cmList{ entry.Value }) {
+ if (uniqueSrcs.insert(ex).second) {
+ cmGeneratorExpression ge(
+ *this->FileSet->GetMakefile()->GetCMakeInstance(),
+ entry.Backtrace);
+ auto cge = ge.Parse(ex);
+ this->CompiledFileEntries.push_back(std::move(cge));
+ }
+ }
+ }
+ }
+
+ return this->CompiledFileEntries;
+}
+
+std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const&
+cmGeneratorFileSet::CompileDirectoryEntries() const
+{
+ if (this->CompiledDirectoryEntries.empty() &&
+ !this->FileSet->GetDirectoryEntries().empty()) {
+ for (auto const& entry : this->FileSet->GetDirectoryEntries()) {
+ for (auto const& ex : cmList{ entry.Value }) {
+ cmGeneratorExpression ge(
+ *this->FileSet->GetMakefile()->GetCMakeInstance(), entry.Backtrace);
+ auto cge = ge.Parse(ex);
+ this->CompiledDirectoryEntries.push_back(std::move(cge));
+ }
+ }
+ }
+
+ return this->CompiledDirectoryEntries;
+}
+
+std::vector<std::string> cmGeneratorFileSet::EvaluateDirectoryEntries(
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges,
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ struct DirCacheEntry
+ {
+ std::string collapsedDir;
+ cm::optional<cmSystemTools::FileId> fileId;
+ };
+
+ std::unordered_map<std::string, DirCacheEntry> dirCache;
+ std::vector<std::string> result;
+ for (auto const& cge : cges) {
+ auto entry = cge->Evaluate(context, dagChecker, target);
+ cmList dirs{ entry };
+ for (std::string dir : dirs) {
+ if (!cmSystemTools::FileIsFullPath(dir)) {
+ dir = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', dir);
+ }
+
+ auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry());
+ auto& dirCacheEntry = dirCacheResult.first->second;
+ auto const isNewCacheEntry = dirCacheResult.second;
+
+ if (isNewCacheEntry) {
+ cmSystemTools::FileId fileId;
+ auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId);
+ dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir);
+ dirCacheEntry.fileId =
+ isFileIdValid ? cm::optional<decltype(fileId)>(fileId) : cm::nullopt;
+ }
+
+ for (auto const& priorDir : result) {
+ auto priorDirCacheEntry = dirCache.at(priorDir);
+ bool sameFile = dirCacheEntry.fileId.has_value() &&
+ priorDirCacheEntry.fileId.has_value() &&
+ (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId);
+ if (!sameFile &&
+ (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir,
+ priorDirCacheEntry.collapsedDir) ||
+ cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir,
+ dirCacheEntry.collapsedDir))) {
+ context.LG->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Base directories in file set cannot be subdirectories of each "
+ "other:\n ",
+ priorDir, "\n ", dir),
+ cge->GetBacktrace());
+ return {};
+ }
+ }
+ result.push_back(dir);
+ }
+ }
+ return result;
+}
+
+void cmGeneratorFileSet::EvaluateFileEntry(
+ std::vector<std::string> const& dirs,
+ std::map<std::string, std::vector<std::string>>& filesPerDir,
+ std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ auto files = cge->Evaluate(context, dagChecker, target);
+ for (std::string file : cmList{ files }) {
+ if (!cmSystemTools::FileIsFullPath(file)) {
+ file = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', file);
+ }
+ auto collapsedFile = cmSystemTools::CollapseFullPath(file);
+ bool found = false;
+ std::string relDir;
+ for (auto const& dir : dirs) {
+ auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
+ if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
+ found = true;
+ relDir = cmSystemTools::GetParentDirectory(
+ cmSystemTools::RelativePath(collapsedDir, collapsedFile));
+ break;
+ }
+ }
+ if (!found) {
+ std::ostringstream e;
+ e << "File:\n " << file
+ << "\nmust be in one of the file set's base directories:";
+ for (auto const& dir : dirs) {
+ e << "\n " << dir;
+ }
+ context.LG->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, e.str(), cge->GetBacktrace());
+ return;
+ }
+
+ filesPerDir[relDir].push_back(file);
+ }
+}
+
+namespace {
+bool EntryIsContextSensitive(
+ std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
+{
+ return cge->GetHadContextSensitiveCondition();
+}
+}
+
+std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
+cmGeneratorFileSet::GetSources(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ std::vector<std::unique_ptr<TargetPropertyEntry>> entries;
+
+ auto directories = this->GetDirectories(context, target, dagChecker);
+ bool contextSensitive = directories.second;
+
+ for (auto const& entry : this->CompileFileEntries()) {
+ auto propEntry = FileSetPropertyEntry::CreateFileSetEntry(
+ directories.first, contextSensitive, entry, this);
+ entries.push_back(std::move(propEntry));
+ }
+
+ return entries;
+}
+
+std::pair<std::vector<std::string>, bool> cmGeneratorFileSet::GetDirectories(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ auto const& directoryEntries = this->CompileDirectoryEntries();
+ auto directories = this->EvaluateDirectoryEntries(directoryEntries, context,
+ target, dagChecker);
+ bool contextSensitive = std::any_of(
+ directoryEntries.begin(), directoryEntries.end(), EntryIsContextSensitive);
+
+ return std::make_pair(std::move(directories), contextSensitive);
+}
+
+std::pair<std::map<std::string, std::vector<std::string>>, bool>
+cmGeneratorFileSet::GetFiles(cm::GenEx::Context const& context,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ auto directories = this->GetDirectories(context, target, dagChecker);
+
+ auto const& fileEntries = this->CompileFileEntries();
+ std::map<std::string, std::vector<std::string>> files;
+ for (auto const& entry : fileEntries) {
+ this->EvaluateFileEntry(directories.first, files, entry, context, target,
+ dagChecker);
+ }
+ bool contextSensitive = directories.second ||
+ std::any_of(fileEntries.begin(), fileEntries.end(),
+ EntryIsContextSensitive);
+
+ return std::make_pair(std::move(files), contextSensitive);
+}
diff --git a/Source/cmGeneratorFileSet.h b/Source/cmGeneratorFileSet.h
new file mode 100644
index 0000000..cfad7e0
--- /dev/null
+++ b/Source/cmGeneratorFileSet.h
@@ -0,0 +1,139 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmFileSetMetadata.h"
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmTargetPropertyEntry.h"
+#include "cmValue.h"
+
+namespace cm {
+namespace GenEx {
+struct Context;
+}
+}
+
+struct cmGeneratorExpressionDAGChecker;
+
+class cmFileSet;
+class cmGeneratorTarget;
+
+class cmGeneratorFileSet
+{
+public:
+ using TargetPropertyEntry = cm::TargetPropertyEntry;
+
+ cmGeneratorFileSet(cmGeneratorTarget const*, cmFileSet const*);
+ ~cmGeneratorFileSet() = default;
+
+ cmGeneratorFileSet(cmGeneratorFileSet&&) = default;
+ cmGeneratorFileSet(cmGeneratorFileSet const&) = delete;
+ cmGeneratorFileSet& operator=(cmGeneratorFileSet const&) = delete;
+
+ std::string const& GetName() const;
+ std::string const& GetType() const;
+ cm::FileSetMetadata::Visibility GetVisibility() const;
+
+ bool IsForSelf() const;
+ bool IsForInterface() const;
+ bool CanBeIncluded() const;
+
+ cmGeneratorTarget const* GetTarget() const { return this->Target; }
+ bool BelongsTo(cmGeneratorTarget const* target) const
+ {
+ return this->Target == target;
+ }
+
+ cmFileSet const* GetFileSet() const { return this->FileSet; }
+
+ cmValue GetProperty(std::string const& prop) const;
+
+ std::vector<BT<std::string>> GetIncludeDirectories(
+ std::string const& config, std::string const& lang) const;
+ std::vector<BT<std::string>> GetInterfaceIncludeDirectories(
+ std::string const& config, std::string const& lang) const;
+
+ std::vector<BT<std::string>> GetCompileOptions(
+ std::string const& config, std::string const& language) const;
+ std::vector<BT<std::string>> GetInterfaceCompileOptions(
+ std::string const& config, std::string const& language) const;
+
+ std::vector<BT<std::string>> GetCompileDefinitions(
+ std::string const& config, std::string const& language) const;
+ std::vector<BT<std::string>> GetInterfaceCompileDefinitions(
+ std::string const& config, std::string const& language) const;
+
+ std::vector<BT<std::string>> const& GetDirectoryEntries() const;
+ std::vector<BT<std::string>> const& GetFileEntries() const;
+
+ std::vector<std::unique_ptr<TargetPropertyEntry>> GetSources(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+ // returned value:
+ // first: list of directories
+ // second: is context sensitive
+ std::pair<std::vector<std::string>, bool> GetDirectories(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+ // returned value:
+ // first: list of files per directory
+ // second: is context sensitive
+ std::pair<std::map<std::string, std::vector<std::string>>, bool> GetFiles(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const&
+ CompileFileEntries() const;
+
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const&
+ CompileDirectoryEntries() const;
+
+ std::vector<std::string> EvaluateDirectoryEntries(
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges,
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+ void EvaluateFileEntry(
+ std::vector<std::string> const& dirs,
+ std::map<std::string, std::vector<std::string>>& filesPerDir,
+ std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+private:
+ cmGeneratorTarget const* Target;
+ cmFileSet const* FileSet;
+ mutable std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
+ CompiledDirectoryEntries;
+ mutable std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
+ CompiledFileEntries;
+
+ using TargetPropertyEntries =
+ std::vector<std::unique_ptr<TargetPropertyEntry>>;
+ TargetPropertyEntries IncludeDirectories;
+ TargetPropertyEntries InterfaceIncludeDirectories;
+ TargetPropertyEntries CompileOptions;
+ TargetPropertyEntries InterfaceCompileOptions;
+ TargetPropertyEntries CompileDefinitions;
+ TargetPropertyEntries InterfaceCompileDefinitions;
+
+ using ConfigAndLanguage = std::pair<std::string, std::string>;
+ using ConfigAndLanguageToBTStrings =
+ std::map<ConfigAndLanguage, std::vector<BT<std::string>>>;
+ mutable ConfigAndLanguageToBTStrings IncludeDirectoriesCache;
+ mutable ConfigAndLanguageToBTStrings InterfaceIncludeDirectoriesCache;
+ mutable ConfigAndLanguageToBTStrings CompileOptionsCache;
+ mutable ConfigAndLanguageToBTStrings InterfaceCompileOptionsCache;
+ mutable ConfigAndLanguageToBTStrings CompileDefinitionsCache;
+ mutable ConfigAndLanguageToBTStrings InterfaceCompileDefinitionsCache;
+};
diff --git a/Source/cmGeneratorFileSets.cxx b/Source/cmGeneratorFileSets.cxx
new file mode 100644
index 0000000..0091751
--- /dev/null
+++ b/Source/cmGeneratorFileSets.cxx
@@ -0,0 +1,436 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmGeneratorFileSets.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cmext/algorithm>
+
+#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
+#include "cmGenExContext.h"
+#include "cmGenExEvaluation.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpressionNode.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
+#include "cmList.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmValue.h"
+
+cmGeneratorFileSets::cmGeneratorFileSets(cmGeneratorTarget* target,
+ cmLocalGenerator* lg)
+ : Target(target)
+ , LocalGenerator(lg)
+{
+ bool isFramework = target->IsFrameworkOnApple();
+ auto issueMessage = [&target](cmFileSet const* fileSet) {
+ target->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(R"(The file set ")", fileSet->GetName(), R"(", of type ")",
+ fileSet->GetType(),
+ R"(", is incompatible with the "FRAMEWORK" target ")",
+ target->GetName(), R"(".)"));
+ };
+
+ for (auto const& name : target->Target->GetAllPrivateFileSets()) {
+ cmFileSet const* fileSet = target->Target->GetFileSet(name);
+ if (isFramework &&
+ !cm::FileSetMetadata::IsFrameworkSupported(fileSet->GetType())) {
+ issueMessage(fileSet);
+ continue;
+ }
+ auto entry = this->FileSets.emplace(
+ name, cm::make_unique<cmGeneratorFileSet>(target, fileSet));
+ auto const* genFileSet = entry.first->second.get();
+ this->AllFileSets.push_back(genFileSet);
+ this->SelfFileSets[genFileSet->GetType()].push_back(genFileSet);
+ }
+ for (auto const& name : target->Target->GetAllInterfaceFileSets()) {
+ auto it = this->FileSets.find(name);
+ cmGeneratorFileSet const* genFileSet = nullptr;
+ if (it == this->FileSets.end()) {
+ cmFileSet const* fileSet = target->Target->GetFileSet(name);
+ if (isFramework &&
+ !cm::FileSetMetadata::IsFrameworkSupported(fileSet->GetType())) {
+ issueMessage(fileSet);
+ continue;
+ }
+ auto entry = this->FileSets.emplace(
+ name, cm::make_unique<cmGeneratorFileSet>(target, fileSet));
+ genFileSet = entry.first->second.get();
+ this->AllFileSets.push_back(genFileSet);
+ } else {
+ genFileSet = it->second.get();
+ }
+ this->InterfaceFileSets[genFileSet->GetType()].push_back(genFileSet);
+ }
+}
+cmGeneratorFileSets::~cmGeneratorFileSets() = default;
+
+std::vector<cm::string_view> cmGeneratorFileSets::GetFileSetTypes() const
+{
+ return cm::keys(this->SelfFileSets);
+}
+
+std::vector<cm::string_view> cmGeneratorFileSets::GetInterfaceFileSetTypes()
+ const
+{
+ return cm::keys(this->InterfaceFileSets);
+}
+
+std::vector<cmGeneratorFileSet const*> const&
+cmGeneratorFileSets::GetAllFileSets() const
+{
+ return this->AllFileSets;
+}
+
+namespace {
+std::vector<cmGeneratorFileSet const*> NoFileSets;
+}
+
+std::vector<cmGeneratorFileSet const*> const& cmGeneratorFileSets::GetFileSets(
+ cm::string_view type) const
+{
+ auto it = this->SelfFileSets.find(type);
+ if (it != this->SelfFileSets.end()) {
+ return it->second;
+ }
+ return NoFileSets;
+}
+std::vector<cmGeneratorFileSet const*> const&
+cmGeneratorFileSets::GetInterfaceFileSets(cm::string_view type) const
+{
+ auto it = this->InterfaceFileSets.find(type);
+ if (it != this->InterfaceFileSets.end()) {
+ return it->second;
+ }
+ return NoFileSets;
+}
+
+cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSet(
+ std::string const& name) const
+{
+ auto const it = this->FileSets.find(name);
+ if (it != this->FileSets.end()) {
+ return it->second.get();
+ }
+ return nullptr;
+}
+
+cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
+ std::string const& config, std::string const& path) const
+{
+ using Lookup = cm::FileSetMetadata::FileSetLookup;
+
+ this->BuildInfoCache(config);
+
+ auto const& info = this->Configs[config];
+
+ auto const it = info.FileSetCache.find(path);
+ if (it != info.FileSetCache.end()) {
+ return it->second;
+ }
+
+ // search in all the dependents
+ auto const it2 = info.InterfaceFileSetCache.find(path);
+ if (it2 != info.InterfaceFileSetCache.end() &&
+ cm::FileSetMetadata::GetFileSetDescriptor(it2->second->GetType())
+ .value_or(cm::FileSetMetadata::FileSetDescriptor{ Lookup::Target })
+ .Lookup == Lookup::Dependencies) {
+ return it2->second;
+ }
+
+ return nullptr;
+}
+cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
+ std::string const& config, cmSourceFile const* sf) const
+{
+ return this->GetFileSetForSource(config, sf->GetFullPath());
+}
+
+std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
+cmGeneratorFileSets::GetSources(
+ std::function<bool(cmGeneratorFileSet const*)> include,
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ std::vector<std::unique_ptr<TargetPropertyEntry>> entries;
+
+ for (auto const& entry : this->FileSets) {
+ auto const* fileSet = entry.second.get();
+ if (include(fileSet)) {
+ auto sources = fileSet->GetSources(context, target, dagChecker);
+ std::move(sources.begin(), sources.end(), std::back_inserter(entries));
+ }
+ }
+
+ return entries;
+}
+
+std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
+cmGeneratorFileSets::GetSources(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ return this->GetSources(
+ [](cmGeneratorFileSet const* fileSet) -> bool {
+ return fileSet->IsForSelf();
+ },
+ context, target, dagChecker);
+}
+std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
+cmGeneratorFileSets::GetSources(
+ std::string type, cm::GenEx::Context const& context,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ return this->GetSources(
+ [&type](cmGeneratorFileSet const* fileSet) -> bool {
+ return fileSet->IsForSelf() && fileSet->GetType() == type;
+ },
+ context, target, dagChecker);
+}
+
+std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
+cmGeneratorFileSets::GetInterfaceSources(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ return this->GetSources(
+ [](cmGeneratorFileSet const* fileSet) -> bool {
+ return fileSet->IsForInterface();
+ },
+ context, target, dagChecker);
+}
+std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
+cmGeneratorFileSets::GetInterfaceSources(
+ std::string type, cm::GenEx::Context const& context,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ return this->GetSources(
+ [&type](cmGeneratorFileSet const* fileSet) -> bool {
+ return fileSet->IsForInterface() && fileSet->GetType() == type;
+ },
+ context, target, dagChecker);
+}
+
+bool cmGeneratorFileSets::MaybeHaveInterfaceProperty(
+ cm::string_view type, std::string const& prop,
+ cm::GenEx::Evaluation* eval) const
+{
+ std::string const key =
+ cmStrCat(type, "::", prop, '@', eval->Context.Config);
+ auto i = this->MaybeInterfacePropertyExists.find(key);
+ if (i == this->MaybeInterfacePropertyExists.end()) {
+ // Insert an entry now in case there is a cycle.
+ i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
+ bool& maybeInterfaceProp = i->second;
+
+ for (auto const* fileSet : this->GetInterfaceFileSets(type)) {
+ // If this file set itself has a non-empty property value, we are done.
+ maybeInterfaceProp = !fileSet->GetProperty(prop).IsEmpty();
+ if (maybeInterfaceProp) {
+ break;
+ }
+ }
+
+ // Otherwise, recurse to interface dependencies.
+ if (!maybeInterfaceProp) {
+ cmGeneratorTarget const* headTarget =
+ eval->HeadTarget ? eval->HeadTarget : this->Target;
+ if (cmLinkInterfaceLibraries const* iface =
+ this->Target->GetLinkInterfaceLibraries(
+ eval->Context.Config, headTarget,
+ cmGeneratorTarget::UseTo::Compile)) {
+ if (iface->HadHeadSensitiveCondition) {
+ // With a different head target we may get to a library with
+ // this interface property.
+ maybeInterfaceProp = true;
+ } else {
+ // The transitive interface libraries do not depend on the
+ // head target, so we can follow them.
+ for (cmLinkItem const& lib : iface->Libraries) {
+ if (lib.Target &&
+ lib.Target->GetGeneratorFileSets()->MaybeHaveInterfaceProperty(
+ type, prop, eval)) {
+ maybeInterfaceProp = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return i->second;
+}
+
+std::string cmGeneratorFileSets::EvaluateInterfaceProperty(
+ cm::string_view type, std::string const& prop, cm::GenEx::Evaluation* eval,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+{
+ // If the property does not appear transitively at all, we are done.
+ if (!this->MaybeHaveInterfaceProperty(type, prop, eval)) {
+ return std::string{};
+ }
+
+ cmList result;
+ cmGeneratorExpressionDAGChecker dagChecker{
+ this->Target, prop, nullptr,
+ dagCheckerParent, eval->Context, eval->Backtrace,
+ };
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ dagChecker.ReportError(
+ eval,
+ cmStrCat("$<FILE_SET_PROPERTY:*,TARGET:", this->Target->GetName(), ',',
+ prop, '>'));
+ return std::string{};
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ // No error. We have already seen this transitive property.
+ return std::string{};
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ cmGeneratorTarget const* headTarget =
+ eval->HeadTarget ? eval->HeadTarget : this->Target;
+
+ for (auto const* fileSet : this->GetInterfaceFileSets(type)) {
+ if (cmValue p = fileSet->GetProperty(prop)) {
+ result.append(cmGeneratorExpressionNode::EvaluateDependentExpression(
+ *p, eval, headTarget, &dagChecker, this->Target));
+ }
+ }
+
+ if (cmLinkInterfaceLibraries const* iface =
+ this->Target->GetLinkInterfaceLibraries(
+ eval->Context.Config, headTarget,
+ cmGeneratorTarget::UseTo::Compile)) {
+ eval->HadContextSensitiveCondition = eval->HadContextSensitiveCondition ||
+ iface->HadContextSensitiveCondition;
+ for (cmLinkItem const& lib : iface->Libraries) {
+ // Broken code can have a target in its own link interface.
+ // Don't follow such link interface entries so as not to create a
+ // self-referencing loop.
+ if (lib.Target && lib.Target != this->Target) {
+ // Pretend $<FILE_SET__PROPERTY:fileSet,TARGET:lib.Target,prop>
+ // appeared in the above property and hand-evaluate it as if it were
+ // compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cm::GenEx::Evaluation libEval(
+ eval->Context, eval->Quiet, headTarget, this->Target,
+ eval->EvaluateForBuildsystem, eval->Backtrace);
+ std::string libResult = cmGeneratorExpression::StripEmptyListElements(
+ lib.Target->GetGeneratorFileSets()->EvaluateInterfaceProperty(
+ type, prop, &libEval, &dagChecker));
+ if (!libResult.empty()) {
+ result.append(libResult);
+ }
+ eval->HadContextSensitiveCondition =
+ eval->HadContextSensitiveCondition ||
+ libEval.HadContextSensitiveCondition;
+ eval->HadHeadSensitiveCondition =
+ eval->HadHeadSensitiveCondition || libEval.HadHeadSensitiveCondition;
+ }
+ }
+ }
+
+ return result.to_string();
+}
+
+namespace {
+void GetInterfaceFiles(cmGeneratorTarget const* target,
+ cm::GenEx::Context const& context,
+ std::unordered_set<cmGeneratorTarget const*>& targets,
+ std::map<std::string, cmGeneratorFileSet const*>& cache)
+{
+ namespace Metadata = cm::FileSetMetadata;
+
+ for (auto const& type : Metadata::GetKnownTypes()) {
+ auto fileSetDescriptor = Metadata::GetFileSetDescriptor(type);
+ if (fileSetDescriptor &&
+ fileSetDescriptor->Lookup == Metadata::FileSetLookup::Dependencies) {
+ for (auto const* fileSet : target->GetInterfaceFileSets(type)) {
+ auto files = fileSet->GetFiles(context, target);
+
+ for (auto const& it : files.first) {
+ for (auto const& filename : it.second) {
+ auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
+ cache[collapsedFile] = fileSet;
+ }
+ }
+ }
+ }
+ }
+
+ if (cmLinkInterfaceLibraries const* iface =
+ target->GetLinkInterfaceLibraries(context.Config, target,
+ cmGeneratorTarget::UseTo::Compile)) {
+ for (cmLinkItem const& lib : iface->Libraries) {
+ if (lib.Target && lib.Target != target &&
+ targets.insert(lib.Target).second) {
+ GetInterfaceFiles(lib.Target, context, targets, cache);
+ }
+ }
+ }
+}
+}
+
+void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const
+{
+ auto& info = this->Configs[config];
+
+ if (info.BuiltCache) {
+ return;
+ }
+
+ cm::GenEx::Context context(this->LocalGenerator, config);
+
+ for (auto const& item : this->FileSets) {
+ auto const* fileSet = item.second.get();
+
+ auto files = fileSet->GetFiles(context, this->Target);
+
+ for (auto const& it : files.first) {
+ for (auto const& filename : it.second) {
+ auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
+ info.FileSetCache[collapsedFile] = fileSet;
+ }
+ }
+ }
+
+ // retrieve all files inherited from dependent targets
+ std::unordered_set<cmGeneratorTarget const*> targets;
+
+ if (cmLinkImplementationLibraries const* impl =
+ this->Target->GetLinkImplementationLibraries(
+ config, cmGeneratorTarget::UseTo::Compile)) {
+ for (cmLinkItem const& lib : impl->Libraries) {
+ if (lib.Target) {
+ GetInterfaceFiles(lib.Target, context, targets,
+ info.InterfaceFileSetCache);
+ }
+ }
+ }
+
+ info.BuiltCache = true;
+}
diff --git a/Source/cmGeneratorFileSets.h b/Source/cmGeneratorFileSets.h
new file mode 100644
index 0000000..3768f39
--- /dev/null
+++ b/Source/cmGeneratorFileSets.h
@@ -0,0 +1,114 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cmTargetPropertyEntry.h"
+
+namespace cm {
+namespace GenEx {
+struct Context;
+struct Evaluation;
+}
+}
+
+struct cmGeneratorExpressionDAGChecker;
+
+class cmSourceFile;
+class cmGeneratorTarget;
+class cmGeneratorFileSet;
+class cmLocalGenerator;
+
+class cmGeneratorFileSets
+{
+public:
+ using TargetPropertyEntry = cm::TargetPropertyEntry;
+
+ cmGeneratorFileSets(cmGeneratorTarget* target, cmLocalGenerator* lg);
+ ~cmGeneratorFileSets();
+
+ cmGeneratorFileSets(cmGeneratorFileSets const&) = delete;
+ cmGeneratorFileSets& operator=(cmGeneratorFileSets const&) = delete;
+
+ bool Empty() const { return this->FileSets.empty(); }
+
+ std::vector<cm::string_view> GetFileSetTypes() const;
+ std::vector<cm::string_view> GetInterfaceFileSetTypes() const;
+
+ std::vector<cmGeneratorFileSet const*> const& GetAllFileSets() const;
+ std::vector<cmGeneratorFileSet const*> const& GetFileSets(
+ cm::string_view type) const;
+ std::vector<cmGeneratorFileSet const*> const& GetInterfaceFileSets(
+ cm::string_view type) const;
+
+ cmGeneratorFileSet const* GetFileSet(std::string const& name) const;
+
+ cmGeneratorFileSet const* GetFileSetForSource(std::string const& config,
+ std::string const& file) const;
+ cmGeneratorFileSet const* GetFileSetForSource(std::string const& config,
+ cmSourceFile const* sf) const;
+
+ std::vector<std::unique_ptr<TargetPropertyEntry>> GetSources(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+ std::vector<std::unique_ptr<TargetPropertyEntry>> GetSources(
+ std::string type, cm::GenEx::Context const& context,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+ std::vector<std::unique_ptr<TargetPropertyEntry>> GetInterfaceSources(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+ std::vector<std::unique_ptr<TargetPropertyEntry>> GetInterfaceSources(
+ std::string type, cm::GenEx::Context const& context,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+ std::string EvaluateInterfaceProperty(
+ cm::string_view type, std::string const& prop, cm::GenEx::Evaluation* eval,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const;
+
+private:
+ std::vector<std::unique_ptr<cm::TargetPropertyEntry>> GetSources(
+ std::function<bool(cmGeneratorFileSet const*)> include,
+ cm::GenEx::Context const& context, cmGeneratorTarget const* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const;
+
+ // file sets indexed by name
+ std::map<std::string, std::unique_ptr<cmGeneratorFileSet>> FileSets;
+ std::vector<cmGeneratorFileSet const*> AllFileSets;
+ // list of private file sets indexed by type
+ std::unordered_map<cm::string_view, std::vector<cmGeneratorFileSet const*>>
+ SelfFileSets;
+ // list of interface file sets indexed by type
+ std::unordered_map<cm::string_view, std::vector<cmGeneratorFileSet const*>>
+ InterfaceFileSets;
+
+ mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
+ bool MaybeHaveInterfaceProperty(cm::string_view type,
+ std::string const& prop,
+ cm::GenEx::Evaluation* eval) const;
+
+ struct InfoByConfig
+ {
+ bool BuiltCache = false;
+ std::map<std::string, cmGeneratorFileSet const*> FileSetCache;
+ std::map<std::string, cmGeneratorFileSet const*> InterfaceFileSetCache;
+ };
+ mutable std::map<std::string, InfoByConfig> Configs;
+
+ void BuildInfoCache(std::string const& config) const;
+
+ cmGeneratorTarget* Target;
+ cmLocalGenerator* LocalGenerator;
+};
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index d44d4bd..a1d016d 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -8,8 +8,8 @@
#include <cstddef>
#include <cstdio>
#include <cstring>
-#include <initializer_list>
#include <sstream>
+#include <string>
#include <unordered_set>
#include <utility>
@@ -28,11 +28,14 @@
#include "cmCxxModuleUsageEffects.h"
#include "cmExperimental.h"
#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmFileTimes.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
@@ -43,7 +46,6 @@
#include "cmPropertyMap.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
#include "cmStandardLevel.h"
#include "cmStandardLevelResolver.h"
@@ -79,22 +81,22 @@
static void CreatePropertyGeneratorExpressions(
cmake& cmakeInstance, cmBTStringRange entries,
- std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
+ std::vector<std::unique_ptr<cm::TargetPropertyEntry>>& items,
bool evaluateForBuildsystem = false)
{
for (auto const& entry : entries) {
- items.emplace_back(cmGeneratorTarget::TargetPropertyEntry::Create(
+ items.emplace_back(cm::TargetPropertyEntry::Create(
cmakeInstance, entry, evaluateForBuildsystem));
}
}
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
: Target(t)
+ , Makefile(t->GetMakefile())
+ , LocalGenerator(lg)
+ , GlobalGenerator(lg->GetGlobalGenerator())
+ , FileSets(cm::make_unique<cmGeneratorFileSets>(this, lg))
{
- this->Makefile = this->Target->GetMakefile();
- this->LocalGenerator = lg;
- this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
-
this->GlobalGenerator->ComputeTargetObjectDirectory(this);
CreatePropertyGeneratorExpressions(*lg->GetCMakeInstance(),
@@ -1005,6 +1007,12 @@
IMPLEMENT_VISIT(SourceKindManifest);
}
+void cmGeneratorTarget::GetRustMainCrateRoot(
+ std::vector<cmSourceFile const*>& data, std::string const& config) const
+{
+ IMPLEMENT_VISIT(SourceKindRustMainCrateRoot);
+}
+
std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
if (!this->UtilityItemsDone) {
@@ -1122,8 +1130,8 @@
// An INTERFACE library is in the build system if it has SOURCES
// or C++ module filesets.
if (!this->SourceEntries.empty() ||
- !this->Target->GetHeaderSetsEntries().empty() ||
- !this->Target->GetCxxModuleSetsEntries().empty()) {
+ !this->GetFileSets(cm::FileSetMetadata::HEADERS).empty() ||
+ !this->GetFileSets(cm::FileSetMetadata::CXX_MODULES).empty()) {
return true;
}
break;
@@ -2343,7 +2351,7 @@
std::string bmiFlags;
auto const* fs = this->GetFileSetForSource(config, sf);
- if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
if (lang != "CXX"_s) {
mf->IssueMessage(
MessageType::FATAL_ERROR,
@@ -2793,6 +2801,14 @@
}
}
+void cmGeneratorTarget::AddRustTargetFlags(std::string& flags) const
+{
+ cmValue const edition = this->GetProperty("Rust_EDITION");
+ if (edition && !edition->empty()) {
+ flags += " --edition=" + *edition;
+ }
+}
+
void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
{
std::string const& compiler =
@@ -4080,8 +4096,16 @@
void cmGeneratorTarget::GetTargetObjectNames(
std::string const& config, std::vector<std::string>& objects) const
{
+ this->GetTargetObjectNames(
+ config, [](cmSourceFile const&) -> bool { return true; }, objects);
+}
+
+void cmGeneratorTarget::GetTargetObjectNames(
+ std::string const& config, std::function<bool(cmSourceFile const&)> filter,
+ std::vector<std::string>& objects) const
+{
this->GetTargetObjectLocations(
- config,
+ config, filter,
[&objects](cmObjectLocation const& buildLoc, cmObjectLocation const&) {
objects.push_back(buildLoc.GetPath());
});
@@ -4092,6 +4116,15 @@
std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
const
{
+ this->GetTargetObjectLocations(
+ config, [](cmSourceFile const&) -> bool { return true; }, cb);
+}
+
+void cmGeneratorTarget::GetTargetObjectLocations(
+ std::string const& config, std::function<bool(cmSourceFile const&)> filter,
+ std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
+ const
+{
std::vector<cmSourceFile const*> objectSources;
this->GetObjectSources(objectSources, config);
std::map<cmSourceFile const*, cmObjectLocations> mapping;
@@ -4108,15 +4141,17 @@
auto const installUseShortPaths = this->GetUseShortObjectNamesForInstall();
for (cmSourceFile const* src : objectSources) {
- // Find the object file name corresponding to this source file.
- auto map_it = mapping.find(src);
- auto const& buildLoc = map_it->second.GetLocation(buildUseShortPaths);
- auto const& installLoc =
- map_it->second.GetInstallLocation(installUseShortPaths, config);
- // It must exist because we populated the mapping just above.
- assert(!buildLoc.GetPath().empty());
- assert(!installLoc.GetPath().empty());
- cb(buildLoc, installLoc);
+ if (filter(*src)) {
+ // Find the object file name corresponding to this source file.
+ auto map_it = mapping.find(src);
+ auto const& buildLoc = map_it->second.GetLocation(buildUseShortPaths);
+ auto const& installLoc =
+ map_it->second.GetInstallLocation(installUseShortPaths, config);
+ // It must exist because we populated the mapping just above.
+ assert(!buildLoc.GetPath().empty());
+ assert(!installLoc.GetPath().empty());
+ cb(buildLoc, installLoc);
+ }
}
// We need to compute the relative path from the root of
@@ -4124,11 +4159,14 @@
std::string rootObjectDir = this->GetObjectDirectory(config);
rootObjectDir = cmSystemTools::CollapseFullPath(rootObjectDir);
auto ispcObjects = this->GetGeneratedISPCObjects(config);
- for (std::string const& output : ispcObjects) {
- auto relativePathFromObjectDir = output.substr(rootObjectDir.size());
- cmObjectLocation ispcLoc(relativePathFromObjectDir);
- // FIXME: apply short path to this object if needed.
- cb(ispcLoc, ispcLoc);
+ for (auto const& output : ispcObjects) {
+ if (filter(*output.first)) {
+ auto relativePathFromObjectDir =
+ output.second.substr(rootObjectDir.size());
+ cmObjectLocation ispcLoc(relativePathFromObjectDir);
+ // FIXME: apply short path to this object if needed.
+ cb(ispcLoc, ispcLoc);
+ }
}
}
@@ -4392,8 +4430,9 @@
return iter->second;
}
-void cmGeneratorTarget::AddISPCGeneratedObject(std::vector<std::string>&& objs,
- std::string const& config)
+void cmGeneratorTarget::AddISPCGeneratedObject(
+ std::vector<std::pair<cmSourceFile const*, std::string>>&& objs,
+ std::string const& config)
{
std::string config_upper;
if (!config.empty()) {
@@ -4407,8 +4446,8 @@
}
}
-std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCObjects(
- std::string const& config) const
+std::vector<std::pair<cmSourceFile const*, std::string>>
+cmGeneratorTarget::GetGeneratedISPCObjects(std::string const& config) const
{
std::string config_upper;
if (!config.empty()) {
@@ -4416,7 +4455,7 @@
}
auto iter = this->ISPCGeneratedObjects.find(config_upper);
if (iter == this->ISPCGeneratedObjects.end()) {
- return std::vector<std::string>{};
+ return std::vector<std::pair<cmSourceFile const*, std::string>>{};
}
return iter->second;
}
@@ -5334,118 +5373,128 @@
return true;
}
-bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
- std::string const& config)
+bool cmGeneratorTarget::DiscoverSyntheticTargets(
+ cmSyntheticTargetCache& cache, std::string const& config,
+ cmGeneratorTarget const* bmiConsumer)
{
std::vector<std::string> allConfigs =
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
cmOptionalLinkImplementation impl;
this->ComputeLinkImplementationLibraries(config, impl, UseTo::Link);
- cmCxxModuleUsageEffects usage(this);
+ if (!bmiConsumer) {
+ bmiConsumer = this;
+ }
+
+ cmCxxModuleUsageEffects usage(bmiConsumer);
auto& SyntheticDeps = this->Configs[config].SyntheticDeps;
for (auto const& entry : impl.Libraries) {
auto const* gt = entry.Target;
- if (!gt || !gt->IsImported()) {
+ if (!gt || !gt->HaveInterfaceCxx20ModuleSources()) {
continue;
}
- if (gt->HaveCxx20ModuleSources()) {
- cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
- constexpr size_t HASH_TRUNCATION = 12;
- auto dirhash = hasher.HashString(
- gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
- std::string safeName = gt->GetName();
- cmSystemTools::ReplaceString(safeName, ":", "_");
- auto targetIdent =
- hasher.HashString(cmStrCat("@d_", dirhash, "@u_", usage.GetHash()));
- std::string targetName =
- cmStrCat(safeName, "@synth_", targetIdent.substr(0, HASH_TRUNCATION));
+ // Visual Studio generators do not currently support BMI-only compilation,
+ // so they can't generate synthetic targets. For consuming native modules,
+ // skip so that the native target is used directly. For imported modules,
+ // create the synth target anyway and diagnose later, in the VS generator.
+ if (!gt->IsImported() && this->GlobalGenerator->IsVisualStudio()) {
+ continue;
+ }
- // Check the cache to see if this instance of the imported target has
- // already been created.
- auto cached = cache.CxxModuleTargets.find(targetName);
- cmGeneratorTarget const* synthDep = nullptr;
- if (cached == cache.CxxModuleTargets.end()) {
- auto const* model = gt->Target;
- auto* mf = gt->Makefile;
- auto* lg = gt->GetLocalGenerator();
- auto* tgt = mf->AddSynthesizedTarget(cmStateEnums::INTERFACE_LIBRARY,
- targetName);
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
+ constexpr size_t HASH_TRUNCATION = 12;
+ auto dirhash =
+ hasher.HashString(gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
+ std::string safeName = gt->GetName();
+ cmSystemTools::ReplaceString(safeName, ":", "_");
+ auto targetIdent =
+ hasher.HashString(cmStrCat("@d_", dirhash, "@u_", usage.GetHash()));
+ std::string targetName =
+ cmStrCat(safeName, "@synth_", targetIdent.substr(0, HASH_TRUNCATION));
- // Copy relevant information from the existing IMPORTED target.
+ // Check the cache to see if this instance of the target has
+ // already been created.
+ auto cached = cache.CxxModuleTargets.find(targetName);
+ cmGeneratorTarget const* synthDep = nullptr;
+ if (cached == cache.CxxModuleTargets.end()) {
+ auto const* model = gt->Target;
+ auto* mf = gt->Makefile;
+ auto* lg = gt->GetLocalGenerator();
+ auto* tgt =
+ mf->AddSynthesizedTarget(cmStateEnums::INTERFACE_LIBRARY, targetName);
- // Copy policies to the target.
- tgt->CopyPolicyStatuses(model);
+ // Copy relevant information from the existing target.
- // Copy file sets.
- {
- auto fsNames = model->GetAllFileSetNames();
- for (auto const& fsName : fsNames) {
- auto const* fs = model->GetFileSet(fsName);
- if (!fs) {
- mf->IssueMessage(MessageType::INTERNAL_ERROR,
- cmStrCat("Failed to find file set named '",
- fsName, "' on target '",
- tgt->GetName(), '\''));
- continue;
- }
- auto* newFs = tgt
- ->GetOrCreateFileSet(fs->GetName(), fs->GetType(),
- fs->GetVisibility())
- .first;
- newFs->CopyEntries(fs);
- }
+ // Copy policies to the target.
+ tgt->CopyPolicyStatuses(model);
+
+ // Copy file sets.
+ {
+ for (auto const* gfs :
+ gt->GetInterfaceFileSets(cm::FileSetMetadata::CXX_MODULES)) {
+ auto* newFs =
+ tgt
+ ->GetOrCreateFileSet(gfs->GetName(), gfs->GetType(),
+ cm::FileSetMetadata::Visibility::Public)
+ .first;
+ newFs->CopyEntries(gfs->GetFileSet());
}
-
- // Copy imported C++ module properties.
- tgt->CopyImportedCxxModulesEntries(model);
-
- // Copy other properties which may affect the C++ module BMI
- // generation.
- tgt->CopyImportedCxxModulesProperties(model);
-
- tgt->AddLinkLibrary(*mf,
- cmStrCat("$<COMPILE_ONLY:", model->GetName(), '>'),
- GENERAL_LibraryType);
-
- // Apply usage requirements to the target.
- usage.ApplyToTarget(tgt);
-
- // Create the generator target and attach it to the local generator.
- auto gtp = cm::make_unique<cmGeneratorTarget>(tgt, lg);
-
- synthDep = gtp.get();
- cache.CxxModuleTargets[targetName] = synthDep;
-
- // See `localGen->ComputeTargetCompileFeatures()` call in
- // `cmGlobalGenerator::Compute` for where non-synthetic targets resolve
- // this.
- for (auto const& innerConfig : allConfigs) {
- gtp->ComputeCompileFeatures(innerConfig);
- }
- // See `cmGlobalGenerator::ApplyCXXStdTargets` in
- // `cmGlobalGenerator::Compute` for non-synthetic target resolutions.
- if (!gtp->ApplyCXXStdTargets()) {
- return false;
- }
-
- gtp->DiscoverSyntheticTargets(cache, config);
-
- lg->AddGeneratorTarget(std::move(gtp));
- } else {
- synthDep = cached->second;
}
- SyntheticDeps[gt].push_back(synthDep);
+ // Copy C++ module properties.
+ tgt->CopyCxxModulesEntries(model);
+
+ // Copy other properties which may affect the C++ module BMI
+ // generation.
+ tgt->CopyCxxModulesProperties(model);
+
+ tgt->AddLinkLibrary(*mf,
+ cmStrCat("$<COMPILE_ONLY:", model->GetName(), '>'),
+ GENERAL_LibraryType);
+
+ // Apply usage requirements to the target.
+ usage.ApplyToTarget(tgt);
+
+ // Create the generator target and attach it to the local generator.
+ auto gtp = cm::make_unique<cmGeneratorTarget>(tgt, lg);
+
+ synthDep = gtp.get();
+ cache.CxxModuleTargets[targetName] = synthDep;
+
+ // See `localGen->ComputeTargetCompileFeatures()` call in
+ // `cmGlobalGenerator::Compute` for where non-synthetic targets resolve
+ // this.
+ for (auto const& innerConfig : allConfigs) {
+ gtp->ComputeCompileFeatures(innerConfig);
+ }
+ // See `cmGlobalGenerator::ApplyCXXStdTargets` in
+ // `cmGlobalGenerator::Compute` for non-synthetic target resolutions.
+ if (!gtp->ApplyCXXStdTargets()) {
+ return false;
+ }
+
+ gtp->DiscoverSyntheticTargets(cache, config, bmiConsumer);
+
+ lg->AddGeneratorTarget(std::move(gtp));
+ } else {
+ synthDep = cached->second;
}
+
+ SyntheticDeps[gt].push_back(synthDep);
}
return true;
}
+cmGeneratorTarget::SyntheticDepsMap const& cmGeneratorTarget::GetSyntheticDeps(
+ std::string const& config) const
+{
+ return this->Configs[config].SyntheticDeps;
+}
+
bool cmGeneratorTarget::HasPackageReferences() const
{
return this->IsInBuildSystem() &&
@@ -5746,324 +5795,6 @@
return this->IsCSharpOnly() ? ManagedType::Managed : ManagedType::Native;
}
-bool cmGeneratorTarget::AddHeaderSetVerification()
-{
- for (bool const isInterface : { false, true }) {
- if (!this->GetPropertyAsBool(isInterface ? "VERIFY_INTERFACE_HEADER_SETS"
- : "VERIFY_PRIVATE_HEADER_SETS")) {
- continue;
- }
-
- if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
- this->GetType() != cmStateEnums::SHARED_LIBRARY &&
- (this->GetType() != cmStateEnums::MODULE_LIBRARY || isInterface) &&
- this->GetType() != cmStateEnums::UNKNOWN_LIBRARY &&
- this->GetType() != cmStateEnums::OBJECT_LIBRARY &&
- this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetType() != cmStateEnums::EXECUTABLE) {
- continue;
- }
-
- char const* headerSetsProperty = isInterface
- ? "INTERFACE_HEADER_SETS_TO_VERIFY"
- : "PRIVATE_HEADER_SETS_TO_VERIFY";
-
- auto verifyValue = this->GetProperty(headerSetsProperty);
- bool const all = verifyValue.IsEmpty();
- std::set<std::string> verifySet;
- if (!all) {
- cmList verifyList{ verifyValue };
- verifySet.insert(verifyList.begin(), verifyList.end());
- }
-
- cmTarget* verifyTarget = nullptr;
- std::string const verifyTargetName =
- cmStrCat(this->GetName(),
- isInterface ? "_verify_interface_header_sets"
- : "_verify_private_header_sets");
-
- char const* allVerifyTargetName = isInterface
- ? "all_verify_interface_header_sets"
- : "all_verify_private_header_sets";
- cmTarget* allVerifyTarget =
- this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse(
- allVerifyTargetName, { cmStateEnums::TargetDomain::NATIVE });
-
- auto fileSetEntries = isInterface
- ? this->Target->GetInterfaceHeaderSetsEntries()
- : this->Target->GetHeaderSetsEntries();
-
- std::set<cmFileSet*> fileSets;
- for (auto const& entry : fileSetEntries) {
- for (auto const& name : cmList{ entry.Value }) {
- if (all || verifySet.count(name)) {
- fileSets.insert(this->Target->GetFileSet(name));
- verifySet.erase(name);
- }
- }
- }
-
- if (isInterface) {
- cmPolicies::PolicyStatus const cmp0209 = this->GetPolicyStatusCMP0209();
- if (cmp0209 != cmPolicies::NEW &&
- this->GetType() == cmStateEnums::EXECUTABLE &&
- !this->GetPropertyAsBool("ENABLE_EXPORTS")) {
- if (cmp0209 == cmPolicies::WARN && !fileSets.empty()) {
- this->Makefile->IssueMessage(
- MessageType::AUTHOR_WARNING,
- cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0209),
- "\n"
- "Executable target \"",
- this->GetName(),
- "\" has interface header file sets, but it does not "
- "enable exports. Those headers would be verified under "
- "CMP0209 NEW behavior.\n"));
- }
- continue;
- }
- }
-
- if (!verifySet.empty()) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Property ", headerSetsProperty, " of target \"",
- this->GetName(),
- "\" contained the following header sets that are nonexistent "
- "or not ",
- isInterface ? "INTERFACE" : "PRIVATE", ":\n ",
- cmJoin(verifySet, "\n ")));
- return false;
- }
-
- cm::optional<std::set<std::string>> languages;
- for (auto* fileSet : fileSets) {
- auto dirCges = fileSet->CompileDirectoryEntries();
- auto fileCges = fileSet->CompileFileEntries();
-
- static auto const contextSensitive =
- [](std::unique_ptr<cmCompiledGeneratorExpression> const& cge) {
- return cge->GetHadContextSensitiveCondition();
- };
- bool dirCgesContextSensitive = false;
- bool fileCgesContextSensitive = false;
-
- std::vector<std::string> dirs;
- std::map<std::string, std::vector<std::string>> filesPerDir;
- bool first = true;
- for (auto const& config : this->Makefile->GetGeneratorConfigs(
- cmMakefile::GeneratorConfigQuery::IncludeEmptyConfig)) {
- cm::GenEx::Context context(this->LocalGenerator, config);
- if (first || dirCgesContextSensitive) {
- dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, this);
- dirCgesContextSensitive =
- std::any_of(dirCges.begin(), dirCges.end(), contextSensitive);
- }
- if (first || fileCgesContextSensitive) {
- filesPerDir.clear();
- for (auto const& fileCge : fileCges) {
- fileSet->EvaluateFileEntry(dirs, filesPerDir, fileCge, context,
- this);
- if (fileCge->GetHadContextSensitiveCondition()) {
- fileCgesContextSensitive = true;
- }
- }
- }
-
- for (auto const& files : filesPerDir) {
- for (auto const& file : files.second) {
- std::string filename = this->GenerateHeaderSetVerificationFile(
- *this->Makefile->GetOrCreateSource(file), files.first,
- verifyTargetName, languages);
- if (filename.empty()) {
- continue;
- }
-
- if (!verifyTarget) {
- {
- cmMakefile::PolicyPushPop polScope(this->Makefile);
- this->Makefile->SetPolicy(cmPolicies::CMP0119,
- cmPolicies::NEW);
- verifyTarget = this->Makefile->AddLibrary(
- verifyTargetName, cmStateEnums::OBJECT_LIBRARY, {}, true);
- }
-
- if (isInterface) {
- // Link to the original target so that we pick up its
- // interface compile options just like a consumer would.
- // This also ensures any generated headers in the original
- // target will be created.
- verifyTarget->AddLinkLibrary(
- *this->Makefile, this->GetName(),
- cmTargetLinkLibraryType::GENERAL_LibraryType);
- } else {
- // For private file sets, we need to simulate compiling the
- // same way as the original target. That includes linking to
- // the same things so we pick up the same transitive
- // properties. For the <LANG>_... properties, we don't care if
- // we set them for languages this target won't eventually use.
- // The verify header sets feature currently only supports the
- // C and C++ languages, so we just always set those here for
- // simplicity rather than working out all languages the target
- // has to compile for.
- static std::vector<std::string> propertiesToCopy = {
- "COMPILE_DEFINITIONS", "COMPILE_FEATURES",
- "COMPILE_FLAGS", "COMPILE_OPTIONS",
- "DEFINE_SYMBOL", "INCLUDE_DIRECTORIES",
- "LINK_LIBRARIES", "C_STANDARD",
- "C_STANDARD_REQUIRED", "C_EXTENSIONS",
- "CXX_STANDARD", "CXX_STANDARD_REQUIRED",
- "CXX_EXTENSIONS"
- };
- for (std::string const& prop : propertiesToCopy) {
- cmValue propValue = this->Target->GetProperty(prop);
- if (propValue.IsSet()) {
- verifyTarget->SetProperty(prop, propValue);
- }
- }
- // The original target might have generated headers. Since
- // we only link to the original target for compilation,
- // there's nothing to force such generation to happen yet.
- // Our verify target must depend on the original target to
- // ensure such generated files will be created.
- verifyTarget->AddUtility(this->GetName(), false,
- this->Makefile);
- verifyTarget->AddCodegenDependency(this->GetName());
- }
-
- verifyTarget->SetProperty("AUTOMOC", "OFF");
- verifyTarget->SetProperty("AUTORCC", "OFF");
- verifyTarget->SetProperty("AUTOUIC", "OFF");
- verifyTarget->SetProperty("DISABLE_PRECOMPILE_HEADERS", "ON");
- verifyTarget->SetProperty("UNITY_BUILD", "OFF");
- verifyTarget->SetProperty("CXX_SCAN_FOR_MODULES", "OFF");
-
- if (isInterface) {
- verifyTarget->FinalizeTargetConfiguration(
- this->Makefile->GetCompileDefinitionsEntries());
- } else {
- // Private verification only needs to add the directory scope
- // definitions here
- for (auto const& def :
- this->Makefile->GetCompileDefinitionsEntries()) {
- verifyTarget->InsertCompileDefinition(def);
- }
- }
-
- if (!allVerifyTarget) {
- allVerifyTarget =
- this->GlobalGenerator->GetMakefiles()
- .front()
- ->AddNewUtilityTarget(allVerifyTargetName, true);
- }
-
- allVerifyTarget->AddUtility(verifyTargetName, false);
- }
-
- if (fileCgesContextSensitive) {
- filename = cmStrCat("$<$<CONFIG:", config, ">:", filename, '>');
- }
- verifyTarget->AddSource(filename);
- }
- }
-
- if (!dirCgesContextSensitive && !fileCgesContextSensitive) {
- break;
- }
- first = false;
- }
- }
-
- if (verifyTarget) {
- this->LocalGenerator->AddGeneratorTarget(
- cm::make_unique<cmGeneratorTarget>(verifyTarget,
- this->LocalGenerator));
- }
- }
-
- return true;
-}
-
-std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile(
- cmSourceFile& source, std::string const& dir,
- std::string const& verifyTargetName,
- cm::optional<std::set<std::string>>& languages) const
-{
- std::string extension;
- std::string language = source.GetOrDetermineLanguage();
-
- if (source.GetPropertyAsBool("SKIP_LINTING")) {
- return std::string{};
- }
-
- if (language.empty()) {
- if (!languages) {
- languages.emplace();
- for (auto const& tgtSource : this->GetAllConfigSources()) {
- auto const& tgtSourceLanguage =
- tgtSource.Source->GetOrDetermineLanguage();
- if (tgtSourceLanguage == "CXX") {
- languages->insert("CXX");
- break; // C++ overrides everything else, so we don't need to keep
- // checking.
- }
- if (tgtSourceLanguage == "C") {
- languages->insert("C");
- }
- }
-
- if (languages->empty()) {
- std::vector<std::string> languagesVector;
- this->GlobalGenerator->GetEnabledLanguages(languagesVector);
- languages->insert(languagesVector.begin(), languagesVector.end());
- }
- }
-
- if (languages->count("CXX")) {
- language = "CXX";
- } else if (languages->count("C")) {
- language = "C";
- }
- }
-
- if (language == "C") {
- extension = ".c";
- } else if (language == "CXX") {
- extension = ".cxx";
- } else {
- return "";
- }
-
- std::string headerFilename = dir;
- if (!headerFilename.empty()) {
- headerFilename += '/';
- }
- headerFilename += source.GetLocation().GetName();
-
- auto filename =
- cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
- verifyTargetName, '/', headerFilename, extension);
- auto* verificationSource = this->Makefile->GetOrCreateSource(filename);
- source.SetSpecialSourceType(
- cmSourceFile::SpecialSourceType::HeaderSetVerificationSource);
- verificationSource->SetProperty("LANGUAGE", language);
-
- cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(filename));
-
- cmGeneratedFileStream fout(filename);
- fout.SetCopyIfDifferent(true);
- // The IWYU "associated" pragma tells include-what-you-use to
- // consider the headerFile as part of the entire language
- // unit within include-what-you-use and as a result allows
- // one to get IWYU advice for headers.
- // Also suppress clang-tidy include checks in generated code.
- fout
- << "/* NOLINTNEXTLINE(misc-header-include-cycle,misc-include-cleaner) */\n"
- << "#include <" << headerFilename << "> /* IWYU pragma: associated */\n";
- fout.close();
-
- return filename;
-}
-
std::string cmGeneratorTarget::GetImportedXcFrameworkPath(
std::string const& config) const
{
@@ -6151,28 +5882,14 @@
return have_direct || have_via_target_objects;
}
-bool cmGeneratorTarget::HaveCxx20ModuleSources(std::string* errorMessage) const
+bool cmGeneratorTarget::HaveInterfaceCxx20ModuleSources() const
{
- auto const& fs_names = this->Target->GetAllFileSetNames();
- return std::any_of(
- fs_names.begin(), fs_names.end(),
- [this, errorMessage](std::string const& name) -> bool {
- auto const* file_set = this->Target->GetFileSet(name);
- if (!file_set) {
- auto message = cmStrCat("Target \"", this->Target->GetName(),
- "\" is tracked to have file set \"", name,
- "\", but it was not found.");
- if (errorMessage) {
- *errorMessage = std::move(message);
- } else {
- this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message);
- }
- return false;
- }
-
- auto const& fs_type = file_set->GetType();
- return fs_type == "CXX_MODULES"_s;
- });
+ return !this->GetInterfaceFileSets(cm::FileSetMetadata::CXX_MODULES).empty();
+}
+bool cmGeneratorTarget::HaveCxx20ModuleSources() const
+{
+ return !this->GetFileSets(cm::FileSetMetadata::CXX_MODULES).empty() ||
+ !this->GetInterfaceFileSets(cm::FileSetMetadata::CXX_MODULES).empty();
}
cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport(
@@ -6314,21 +6031,6 @@
return lang == "Fortran"_s || this->NeedCxxModuleSupport(lang, config);
}
-cmFileSet const* cmGeneratorTarget::GetFileSetForSource(
- std::string const& config, cmSourceFile const* sf) const
-{
- this->BuildFileSetInfoCache(config);
-
- auto const& path = sf->GetFullPath();
- auto const& per_config = this->Configs[config];
-
- auto const fsit = per_config.FileSetCache.find(path);
- if (fsit == per_config.FileSetCache.end()) {
- return nullptr;
- }
- return fsit->second;
-}
-
bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang,
std::string const& config,
cmSourceFile const* sf) const
@@ -6345,7 +6047,7 @@
// Any file in `CXX_MODULES` file sets need scanned (it being `CXX` is
// enforced elsewhere).
auto const* fs = this->GetFileSetForSource(config, sf);
- if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
return true;
}
@@ -6353,6 +6055,12 @@
if (targetDyndep == CxxModuleSupport::Unavailable) {
return false;
}
+ if (fs) {
+ auto const fsProp = fs->GetProperty("CXX_SCAN_FOR_MODULES");
+ if (fsProp.IsSet()) {
+ return fsProp.IsOn();
+ }
+ }
auto const sfProp = sf->GetProperty("CXX_SCAN_FOR_MODULES");
if (sfProp.IsSet()) {
return sfProp.IsOn();
@@ -6403,6 +6111,40 @@
return policyAnswer;
}
+bool cmGeneratorTarget::HasFileSets() const
+{
+ return !this->FileSets->Empty();
+}
+
+std::vector<cmGeneratorFileSet const*> const&
+cmGeneratorTarget::GetAllFileSets() const
+{
+ return this->FileSets->GetAllFileSets();
+}
+
+std::vector<cmGeneratorFileSet const*> const& cmGeneratorTarget::GetFileSets(
+ cm::string_view type) const
+{
+ return this->FileSets->GetFileSets(type);
+}
+std::vector<cmGeneratorFileSet const*> const&
+cmGeneratorTarget::GetInterfaceFileSets(cm::string_view type) const
+{
+ return this->FileSets->GetInterfaceFileSets(type);
+}
+
+cmGeneratorFileSet const* cmGeneratorTarget::GetFileSet(
+ std::string const& name) const
+{
+ return this->FileSets->GetFileSet(name);
+}
+
+cmGeneratorFileSet const* cmGeneratorTarget::GetFileSetForSource(
+ std::string const& config, cmSourceFile const* sf) const
+{
+ return this->FileSets->GetFileSetForSource(config, sf);
+}
+
std::string cmGeneratorTarget::BuildDatabasePath(
std::string const& lang, std::string const& config) const
{
@@ -6428,50 +6170,6 @@
"_build_database.json");
}
-void cmGeneratorTarget::BuildFileSetInfoCache(std::string const& config) const
-{
- auto& per_config = this->Configs[config];
-
- if (per_config.BuiltFileSetCache) {
- return;
- }
-
- auto const* tgt = this->Target;
-
- for (auto const& name : tgt->GetAllFileSetNames()) {
- auto const* file_set = tgt->GetFileSet(name);
- if (!file_set) {
- tgt->GetMakefile()->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("Target \"", tgt->GetName(),
- "\" is tracked to have file set \"", name,
- "\", but it was not found."));
- continue;
- }
-
- cm::GenEx::Context context(this->LocalGenerator, config);
-
- auto fileEntries = file_set->CompileFileEntries();
- auto directoryEntries = file_set->CompileDirectoryEntries();
- auto directories =
- file_set->EvaluateDirectoryEntries(directoryEntries, context, this);
-
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- file_set->EvaluateFileEntry(directories, files, entry, context, this);
- }
-
- for (auto const& it : files) {
- for (auto const& filename : it.second) {
- auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
- per_config.FileSetCache[collapsedFile] = file_set;
- }
- }
- }
-
- per_config.BuiltFileSetCache = true;
-}
-
std::string cmGeneratorTarget::GetSwiftModuleName() const
{
return this->GetPropertyOrDefault("Swift_MODULE_NAME", this->GetName());
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index a32ecba..bed66b8 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -27,6 +27,7 @@
#include "cmSourceFile.h"
#include "cmStandardLevel.h"
#include "cmStateTypes.h"
+#include "cmTargetPropertyEntry.h"
#include "cmValue.h"
namespace cm {
@@ -36,12 +37,11 @@
}
}
-class cmake;
enum class cmBuildStep;
-class cmCompiledGeneratorExpression;
class cmComputeLinkInformation;
class cmCustomCommand;
-class cmFileSet;
+class cmGeneratorFileSets;
+class cmGeneratorFileSet;
class cmGlobalGenerator;
class cmLocalGenerator;
class cmMakefile;
@@ -53,6 +53,8 @@
class cmGeneratorTarget
{
public:
+ using TargetPropertyEntry = cm::TargetPropertyEntry;
+
cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg);
~cmGeneratorTarget();
@@ -143,6 +145,7 @@
SourceKindCustomCommand,
SourceKindExternalObject,
SourceKindCxxModuleSource,
+ SourceKindRustMainCrateRoot,
SourceKindExtra,
SourceKindHeader,
SourceKindIDL,
@@ -222,6 +225,9 @@
void GetManifests(std::vector<cmSourceFile const*>&,
std::string const& config) const;
+ void GetRustMainCrateRoot(std::vector<cmSourceFile const*>&,
+ std::string const& config) const;
+
std::set<cmLinkItem> const& GetUtilityItems() const;
void ComputeObjectMapping();
@@ -311,11 +317,18 @@
its object file directory for the build. */
void GetTargetObjectNames(std::string const& config,
std::vector<std::string>& objects) const;
+ void GetTargetObjectNames(std::string const& config,
+ std::function<bool(cmSourceFile const&)> filter,
+ std::vector<std::string>& objects) const;
/** Get the build and install locations of objects for a given context. */
void GetTargetObjectLocations(
std::string const& config,
std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
const;
+ void GetTargetObjectLocations(
+ std::string const& config, std::function<bool(cmSourceFile const&)> filter,
+ std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
+ const;
/** What hierarchy level should the reported directory contain */
enum BundleDirectoryLevel
@@ -613,6 +626,8 @@
void AddISPCTargetFlags(std::string& flags) const;
+ void AddRustTargetFlags(std::string& flags) const;
+
std::string GetFeatureSpecificLinkRuleVariable(
std::string const& var, std::string const& lang,
std::string const& config) const;
@@ -1014,8 +1029,6 @@
std::string const& report,
std::string const& compatibilityType) const;
- class TargetPropertyEntry;
-
std::string EvaluateInterfaceProperty(
std::string const& prop, cm::GenEx::Evaluation* eval,
cmGeneratorExpressionDAGChecker* dagCheckerParent, UseTo usage) const;
@@ -1102,24 +1115,38 @@
std::vector<std::string> GetGeneratedISPCHeaders(
std::string const& config) const;
- void AddISPCGeneratedObject(std::vector<std::string>&& objs,
- std::string const& config);
- std::vector<std::string> GetGeneratedISPCObjects(
- std::string const& config) const;
+ void AddISPCGeneratedObject(
+ std::vector<std::pair<cmSourceFile const*, std::string>>&& objs,
+ std::string const& config);
+ std::vector<std::pair<cmSourceFile const*, std::string>>
+ GetGeneratedISPCObjects(std::string const& config) const;
void AddSystemIncludeDirectory(std::string const& inc,
std::string const& lang);
bool AddHeaderSetVerification();
- std::string GenerateHeaderSetVerificationFile(
+ cm::optional<std::string> GenerateHeaderSetVerificationFile(
cmSourceFile& source, std::string const& dir,
std::string const& verifyTargetName,
- cm::optional<std::set<std::string>>& languages) const;
+ cm::optional<cm::optional<std::string>>& defaultLanguage) const;
+
+ cm::optional<std::string> ResolveHeaderLanguage(
+ cmSourceFile& source,
+ cm::optional<cm::optional<std::string>>& defaultLanguage) const;
+
+ cm::optional<std::string> GenerateStubForLanguage(
+ std::string const& language, std::string const& headerFilename,
+ std::string const& verifyTargetName, cmSourceFile& source) const;
std::string GetImportedXcFrameworkPath(std::string const& config) const;
bool ApplyCXXStdTargets();
- bool DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
- std::string const& config);
+ bool DiscoverSyntheticTargets(
+ cmSyntheticTargetCache& cache, std::string const& config,
+ cmGeneratorTarget const* bmiConsumer = nullptr);
+
+ using SyntheticDepsMap =
+ std::map<cmGeneratorTarget const*, std::vector<cmGeneratorTarget const*>>;
+ SyntheticDepsMap const& GetSyntheticDeps(std::string const& config) const;
class CustomTransitiveProperty : public TransitiveProperty
{
@@ -1357,7 +1384,8 @@
std::unordered_map<std::string, std::vector<std::string>>
ISPCGeneratedHeaders;
- std::unordered_map<std::string, std::vector<std::string>>
+ std::unordered_map<std::string,
+ std::vector<std::pair<cmSourceFile const*, std::string>>>
ISPCGeneratedObjects;
enum class LinkInterfaceField
@@ -1494,6 +1522,22 @@
bool HaveFortranSources() const;
bool HaveFortranSources(std::string const& config) const;
+ // File sets support queries
+
+ bool HasFileSets() const;
+ cmGeneratorFileSets const* GetGeneratorFileSets() const
+ {
+ return this->FileSets.get();
+ }
+ std::vector<cmGeneratorFileSet const*> const& GetAllFileSets() const;
+ std::vector<cmGeneratorFileSet const*> const& GetFileSets(
+ cm::string_view type) const;
+ std::vector<cmGeneratorFileSet const*> const& GetInterfaceFileSets(
+ cm::string_view type) const;
+ cmGeneratorFileSet const* GetFileSet(std::string const& name) const;
+ cmGeneratorFileSet const* GetFileSetForSource(std::string const& config,
+ cmSourceFile const* sf) const;
+
// C++20 module support queries.
/**
@@ -1501,11 +1545,9 @@
*
* This will inspect the target itself to see if C++20 module
* support is expected to work based on its sources.
- *
- * If `errorMessage` is given a non-`nullptr`, any error message will be
- * stored in it, otherwise the error will be reported directly.
*/
- bool HaveCxx20ModuleSources(std::string* errorMessage = nullptr) const;
+ bool HaveInterfaceCxx20ModuleSources() const;
+ bool HaveCxx20ModuleSources() const;
enum class Cxx20SupportLevel
{
@@ -1518,6 +1560,7 @@
// C++20 modules are available and working.
Supported,
};
+
/**
* Query whether the target has C++20 module support available (regardless of
* whether it is required or not).
@@ -1530,8 +1573,6 @@
bool NeedCxxModuleSupport(std::string const& lang,
std::string const& config) const;
bool NeedDyndep(std::string const& lang, std::string const& config) const;
- cmFileSet const* GetFileSetForSource(std::string const& config,
- cmSourceFile const* sf) const;
bool NeedDyndepForSource(std::string const& lang, std::string const& config,
cmSourceFile const* sf) const;
enum class CxxModuleSupport
@@ -1557,45 +1598,15 @@
static MsvcCharSet GetMsvcCharSet(std::string const& singleDefine);
private:
- void BuildFileSetInfoCache(std::string const& config) const;
struct InfoByConfig
{
- bool BuiltFileSetCache = false;
- std::map<std::string, cmFileSet const*> FileSetCache;
std::map<cmGeneratorTarget const*, std::vector<cmGeneratorTarget const*>>
SyntheticDeps;
std::map<cmSourceFile const*, ClassifiedFlags> SourceFlags;
};
mutable std::map<std::string, InfoByConfig> Configs;
+ std::unique_ptr<cmGeneratorFileSets> FileSets;
bool PchReused = false;
mutable bool ComputingPchReuse = false;
mutable bool PchReuseCycleDetected = false;
};
-
-class cmGeneratorTarget::TargetPropertyEntry
-{
-protected:
- static cmLinkItem NoLinkItem;
-
-public:
- TargetPropertyEntry(cmLinkItem const& item);
- virtual ~TargetPropertyEntry() = default;
-
- static std::unique_ptr<TargetPropertyEntry> Create(
- cmake& cmakeInstance, const BT<std::string>& propertyValue,
- bool evaluateForBuildsystem = false);
- static std::unique_ptr<TargetPropertyEntry> CreateFileSet(
- std::vector<std::string> dirs, bool contextSensitiveDirs,
- std::unique_ptr<cmCompiledGeneratorExpression> entryCge,
- cmFileSet const* fileSet, cmLinkItem const& item = NoLinkItem);
-
- virtual std::string const& Evaluate(
- cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker) const = 0;
-
- virtual cmListFileBacktrace GetBacktrace() const = 0;
- virtual std::string const& GetInput() const = 0;
- virtual bool GetHadContextSensitiveCondition() const;
-
- cmLinkItem const& LinkItem;
-};
diff --git a/Source/cmGeneratorTarget_HeaderSetVerification.cxx b/Source/cmGeneratorTarget_HeaderSetVerification.cxx
new file mode 100644
index 0000000..a4420f1
--- /dev/null
+++ b/Source/cmGeneratorTarget_HeaderSetVerification.cxx
@@ -0,0 +1,426 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+/* clang-format off */
+#include "cmGeneratorTarget.h"
+/* clang-format on */
+
+#include <algorithm>
+#include <array>
+#include <initializer_list>
+#include <map>
+#include <ostream>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cm/string_view>
+
+#include "cmFileSetMetadata.h"
+#include "cmGenExContext.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGlobalGenerator.h"
+#include "cmList.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetLinkLibraryType.h"
+#include "cmValue.h"
+
+bool cmGeneratorTarget::AddHeaderSetVerification()
+{
+ for (bool const isInterface : { false, true }) {
+ if (!this->GetPropertyAsBool(isInterface ? "VERIFY_INTERFACE_HEADER_SETS"
+ : "VERIFY_PRIVATE_HEADER_SETS")) {
+ continue;
+ }
+
+ if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ (this->GetType() != cmStateEnums::MODULE_LIBRARY || isInterface) &&
+ this->GetType() != cmStateEnums::UNKNOWN_LIBRARY &&
+ this->GetType() != cmStateEnums::OBJECT_LIBRARY &&
+ this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ continue;
+ }
+
+ char const* headerSetsProperty = isInterface
+ ? "INTERFACE_HEADER_SETS_TO_VERIFY"
+ : "PRIVATE_HEADER_SETS_TO_VERIFY";
+
+ auto verifyValue = this->GetProperty(headerSetsProperty);
+ bool const all = verifyValue.IsEmpty();
+ std::set<std::string> verifySet;
+ if (!all) {
+ cmList verifyList{ verifyValue };
+ verifySet.insert(verifyList.begin(), verifyList.end());
+ }
+
+ cmTarget* verifyTarget = nullptr;
+ std::string const verifyTargetName =
+ cmStrCat(this->GetName(),
+ isInterface ? "_verify_interface_header_sets"
+ : "_verify_private_header_sets");
+
+ char const* allVerifyTargetName = isInterface
+ ? "all_verify_interface_header_sets"
+ : "all_verify_private_header_sets";
+ cmTarget* allVerifyTarget =
+ this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse(
+ allVerifyTargetName, { cmStateEnums::TargetDomain::NATIVE });
+
+ auto fileSetEntries = isInterface
+ ? this->GetInterfaceFileSets(cm::FileSetMetadata::HEADERS)
+ : this->GetFileSets(cm::FileSetMetadata::HEADERS);
+
+ std::set<cmGeneratorFileSet const*> fileSets;
+ for (auto const& fileSet : fileSetEntries) {
+ if (all || verifySet.count(fileSet->GetName())) {
+ fileSets.insert(fileSet);
+ verifySet.erase(fileSet->GetName());
+ }
+ }
+
+ if (isInterface) {
+ cmPolicies::PolicyStatus const cmp0209 = this->GetPolicyStatusCMP0209();
+ if (cmp0209 != cmPolicies::NEW &&
+ this->GetType() == cmStateEnums::EXECUTABLE &&
+ !this->GetPropertyAsBool("ENABLE_EXPORTS")) {
+ if (cmp0209 == cmPolicies::WARN && !fileSets.empty()) {
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0209),
+ "\n"
+ "Executable target \"",
+ this->GetName(),
+ "\" has interface header file sets, but it does not "
+ "enable exports. Those headers would be verified under "
+ "CMP0209 NEW behavior.\n"));
+ }
+ continue;
+ }
+ }
+
+ if (!verifySet.empty()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Property ", headerSetsProperty, " of target \"",
+ this->GetName(),
+ "\" contained the following header sets that are nonexistent "
+ "or not ",
+ isInterface ? "INTERFACE" : "PRIVATE", ":\n ",
+ cmJoin(verifySet, "\n ")));
+ return false;
+ }
+
+ cm::optional<cm::optional<std::string>> defaultLanguage;
+
+ // First, collect all verification stubs before creating the target,
+ // so we know whether to create an OBJECT library or not.
+ std::vector<std::string> stubSources;
+ for (auto const* fileSet : fileSets) {
+ auto const& dirCges = fileSet->CompileDirectoryEntries();
+ auto const& fileCges = fileSet->CompileFileEntries();
+
+ static auto const contextSensitive =
+ [](std::unique_ptr<cmCompiledGeneratorExpression> const& cge) {
+ return cge->GetHadContextSensitiveCondition();
+ };
+ bool dirCgesContextSensitive = false;
+ bool fileCgesContextSensitive = false;
+
+ std::vector<std::string> dirs;
+ std::map<std::string, std::vector<std::string>> filesPerDir;
+ bool first = true;
+ for (auto const& config : this->Makefile->GetGeneratorConfigs(
+ cmMakefile::GeneratorConfigQuery::IncludeEmptyConfig)) {
+ cm::GenEx::Context context(this->LocalGenerator, config);
+ if (first || dirCgesContextSensitive) {
+ dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, this);
+ dirCgesContextSensitive =
+ std::any_of(dirCges.begin(), dirCges.end(), contextSensitive);
+ }
+ if (first || fileCgesContextSensitive) {
+ filesPerDir.clear();
+ for (auto const& fileCge : fileCges) {
+ fileSet->EvaluateFileEntry(dirs, filesPerDir, fileCge, context,
+ this);
+ if (fileCge->GetHadContextSensitiveCondition()) {
+ fileCgesContextSensitive = true;
+ }
+ }
+ }
+
+ for (auto const& files : filesPerDir) {
+ for (auto const& file : files.second) {
+ cm::optional<std::string> filenameOpt =
+ this->GenerateHeaderSetVerificationFile(
+ *this->Makefile->GetOrCreateSource(file), files.first,
+ verifyTargetName, defaultLanguage);
+ if (!filenameOpt) {
+ continue;
+ }
+ std::string filename = *filenameOpt;
+
+ if (fileCgesContextSensitive) {
+ filename = cmStrCat("$<$<CONFIG:", config, ">:", filename, '>');
+ }
+ stubSources.emplace_back(std::move(filename));
+ }
+ }
+
+ if (!dirCgesContextSensitive && !fileCgesContextSensitive) {
+ break;
+ }
+ first = false;
+ }
+ }
+
+ if (stubSources.empty()) {
+ // No headers to verify. Create a utility target so the target
+ // name always exists (e.g. for build system dependencies) without
+ // needing a placeholder source. This avoids warnings from tools
+ // like Xcode's libtool about empty static libraries.
+ verifyTarget =
+ this->Makefile->AddNewUtilityTarget(verifyTargetName, true);
+ } else {
+ // Create an OBJECT library to compile the verification stubs.
+ {
+ cmMakefile::PolicyPushPop polScope(this->Makefile);
+ this->Makefile->SetPolicy(cmPolicies::CMP0119, cmPolicies::NEW);
+ verifyTarget = this->Makefile->AddLibrary(
+ verifyTargetName, cmStateEnums::OBJECT_LIBRARY, {}, true);
+ }
+
+ if (isInterface) {
+ // Link to the original target so that we pick up its
+ // interface compile options just like a consumer would.
+ // This also ensures any generated headers in the original
+ // target will be created.
+ verifyTarget->AddLinkLibrary(
+ *this->Makefile, this->GetName(),
+ cmTargetLinkLibraryType::GENERAL_LibraryType);
+ } else {
+ // For private file sets, we need to simulate compiling the
+ // same way as the original target. That includes linking to
+ // the same things so we pick up the same transitive
+ // properties. For the <LANG>_... properties, we don't care if
+ // we set them for languages this target won't eventually use.
+ // Copy language-standard properties for all supported
+ // languages. We don't care if we set properties for languages
+ // this target won't eventually use.
+ static std::array<std::string, 19> const propertiesToCopy{ {
+ "COMPILE_DEFINITIONS", "COMPILE_FEATURES",
+ "COMPILE_FLAGS", "COMPILE_OPTIONS",
+ "DEFINE_SYMBOL", "INCLUDE_DIRECTORIES",
+ "LINK_LIBRARIES", "C_STANDARD",
+ "C_STANDARD_REQUIRED", "C_EXTENSIONS",
+ "CXX_STANDARD", "CXX_STANDARD_REQUIRED",
+ "CXX_EXTENSIONS", "OBJC_STANDARD",
+ "OBJC_STANDARD_REQUIRED", "OBJC_EXTENSIONS",
+ "OBJCXX_STANDARD", "OBJCXX_STANDARD_REQUIRED",
+ "OBJCXX_EXTENSIONS",
+ } };
+ for (std::string const& prop : propertiesToCopy) {
+ cmValue propValue = this->Target->GetProperty(prop);
+ if (propValue.IsSet()) {
+ verifyTarget->SetProperty(prop, propValue);
+ }
+ }
+ // The original target might have generated headers. Since
+ // we only link to the original target for compilation,
+ // there's nothing to force such generation to happen yet.
+ // Our verify target must depend on the original target to
+ // ensure such generated files will be created.
+ verifyTarget->AddUtility(this->GetName(), false, this->Makefile);
+ verifyTarget->AddCodegenDependency(this->GetName());
+ }
+
+ verifyTarget->SetProperty("AUTOMOC", "OFF");
+ verifyTarget->SetProperty("AUTORCC", "OFF");
+ verifyTarget->SetProperty("AUTOUIC", "OFF");
+ verifyTarget->SetProperty("DISABLE_PRECOMPILE_HEADERS", "ON");
+ verifyTarget->SetProperty("UNITY_BUILD", "OFF");
+ verifyTarget->SetProperty("CXX_SCAN_FOR_MODULES", "OFF");
+
+ if (isInterface) {
+ verifyTarget->FinalizeTargetConfiguration(
+ this->Makefile->GetCompileDefinitionsEntries());
+ } else {
+ // Private verification only needs to add the directory scope
+ // definitions here
+ for (auto const& def :
+ this->Makefile->GetCompileDefinitionsEntries()) {
+ verifyTarget->InsertCompileDefinition(def);
+ }
+ }
+
+ for (auto const& source : stubSources) {
+ verifyTarget->AddSource(source);
+ }
+ }
+ if (!allVerifyTarget) {
+ allVerifyTarget =
+ this->GlobalGenerator->GetMakefiles().front()->AddNewUtilityTarget(
+ allVerifyTargetName, true);
+ }
+ allVerifyTarget->AddUtility(verifyTargetName, false);
+
+ this->LocalGenerator->AddGeneratorTarget(
+ cm::make_unique<cmGeneratorTarget>(verifyTarget, this->LocalGenerator));
+ }
+ return true;
+}
+
+cm::optional<std::string> cmGeneratorTarget::GenerateHeaderSetVerificationFile(
+ cmSourceFile& source, std::string const& dir,
+ std::string const& verifyTargetName,
+ cm::optional<cm::optional<std::string>>& defaultLanguage) const
+{
+ if (source.GetPropertyAsBool("SKIP_LINTING")) {
+ return cm::nullopt;
+ }
+
+ cm::optional<std::string> language =
+ this->ResolveHeaderLanguage(source, defaultLanguage);
+ if (!language) {
+ return cm::nullopt;
+ }
+
+ std::string headerFilename = dir;
+ if (!headerFilename.empty()) {
+ headerFilename += '/';
+ }
+ headerFilename += source.GetLocation().GetName();
+
+ return this->GenerateStubForLanguage(*language, headerFilename,
+ verifyTargetName, source);
+}
+
+cm::optional<std::string> cmGeneratorTarget::ResolveHeaderLanguage(
+ cmSourceFile& source,
+ cm::optional<cm::optional<std::string>>& defaultLanguage) const
+{
+ static std::array<cm::string_view, 4> const supportedLangs{ {
+ "C",
+ "CXX",
+ "OBJC",
+ "OBJCXX",
+ } };
+ auto isSupported = [](cm::string_view lang) -> bool {
+ return std::find(supportedLangs.begin(), supportedLangs.end(), lang) !=
+ supportedLangs.end();
+ };
+
+ // If the source has an explicit language, validate and return it.
+ std::string language = source.GetOrDetermineLanguage();
+ if (!language.empty()) {
+ if (!isSupported(language)) {
+ return cm::nullopt;
+ }
+ return cm::optional<std::string>(std::move(language));
+ }
+
+ /*
+ Compute and cache the default language for unlanguaged headers.
+ The lattice join is run once per file set, not once per header.
+ Lattice: OBJCXX
+ / \
+ CXX OBJC
+ \ /
+ C
+ */
+ if (!defaultLanguage) {
+ std::set<std::string> langs;
+ for (AllConfigSource const& tgtSource : this->GetAllConfigSources()) {
+ std::string const& lang = tgtSource.Source->GetOrDetermineLanguage();
+ if (isSupported(lang)) {
+ langs.insert(lang);
+ }
+ }
+ if (langs.empty()) {
+ std::vector<std::string> languagesVector;
+ this->GlobalGenerator->GetEnabledLanguages(languagesVector);
+ for (std::string const& lang : languagesVector) {
+ if (isSupported(lang)) {
+ langs.insert(lang);
+ }
+ }
+ }
+
+ cm::optional<std::string> resolved;
+ if (langs.count("OBJCXX") || (langs.count("CXX") && langs.count("OBJC"))) {
+ resolved = "OBJCXX"; // promote
+ } else if (langs.count("CXX")) {
+ resolved = "CXX";
+ } else if (langs.count("OBJC")) {
+ resolved = "OBJC";
+ } else if (langs.count("C")) {
+ resolved = "C";
+ }
+ defaultLanguage = resolved;
+ }
+
+ return *defaultLanguage;
+}
+
+cm::optional<std::string> cmGeneratorTarget::GenerateStubForLanguage(
+ std::string const& language, std::string const& headerFilename,
+ std::string const& verifyTargetName, cmSourceFile& source) const
+{
+ static std::array<std::pair<cm::string_view, cm::string_view>, 4> const
+ langToExt = { {
+ { "C", ".c" },
+ { "CXX", ".cxx" },
+ { "OBJC", ".m" },
+ { "OBJCXX", ".mm" },
+ } };
+
+ // NOLINTNEXTLINE(readability-qualified-auto)
+ auto const it =
+ std::find_if(langToExt.begin(), langToExt.end(),
+ [&](std::pair<cm::string_view, cm::string_view> const& p) {
+ return p.first == language;
+ });
+ if (it == langToExt.end()) {
+ return cm::nullopt;
+ }
+
+ std::string filename =
+ cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ verifyTargetName, '/', headerFilename, it->second);
+
+ cmSourceFile* verificationSource =
+ this->Makefile->GetOrCreateSource(filename);
+ source.SetSpecialSourceType(
+ cmSourceFile::SpecialSourceType::HeaderSetVerificationSource);
+ verificationSource->SetProperty("LANGUAGE", language);
+
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(filename));
+
+ cmGeneratedFileStream fout(filename);
+ fout.SetCopyIfDifferent(true);
+ // The IWYU "associated" pragma tells include-what-you-use to
+ // consider the headerFile as part of the entire language
+ // unit within include-what-you-use and as a result allows
+ // one to get IWYU advice for headers.
+ // Also suppress clang-tidy include checks in generated code.
+ fout
+ << "/* NOLINTNEXTLINE(misc-header-include-cycle,misc-include-cleaner) */\n"
+ << "#include <" << headerFilename << "> /* IWYU pragma: associated */\n";
+ fout.close();
+
+ return cm::optional<std::string>(std::move(filename));
+}
diff --git a/Source/cmGeneratorTarget_IncludeDirectories.cxx b/Source/cmGeneratorTarget_IncludeDirectories.cxx
index c91d25b..b8047e8 100644
--- a/Source/cmGeneratorTarget_IncludeDirectories.cxx
+++ b/Source/cmGeneratorTarget_IncludeDirectories.cxx
@@ -97,7 +97,7 @@
void AddLangSpecificImplicitIncludeDirectories(
cmGeneratorTarget const* target, std::string const& lang,
std::string const& config, std::string const& propertyName,
- IncludeDirectoryFallBack mode, EvaluatedTargetPropertyEntries& entries)
+ IncludeDirectoryFallBack mode, cm::EvaluatedTargetPropertyEntries& entries)
{
if (auto const* libraries =
target->GetLinkImplementationLibraries(config, UseTo::Compile)) {
@@ -113,7 +113,7 @@
}
if (cm::contains(dependency->GetAllConfigCompileLanguages(), lang)) {
auto* lg = dependency->GetLocalGenerator();
- EvaluatedTargetPropertyEntry entry{ library, library.Backtrace };
+ cm::EvaluatedTargetPropertyEntry entry{ library, library.Backtrace };
if (lang == "Swift") {
entry.Values.emplace_back(
@@ -141,12 +141,12 @@
}
void processIncludeDirectories(cmGeneratorTarget const* tgt,
- EvaluatedTargetPropertyEntries& entries,
+ cm::EvaluatedTargetPropertyEntries& entries,
std::vector<BT<std::string>>& includes,
std::unordered_set<std::string>& uniqueIncludes,
bool debugIncludes)
{
- for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
+ for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
cmLinkItem const& item = entry.LinkItem;
std::string const& targetName = item.AsStr();
bool const fromImported = item.Target && item.Target->IsImported();
@@ -237,8 +237,9 @@
this->DebugIncludesDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->IncludeDirectoriesEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->IncludeDirectoriesEntries);
if (lang == "Swift") {
AddLangSpecificImplicitIncludeDirectories(
@@ -266,7 +267,7 @@
}
AddInterfaceEntries(this, "INTERFACE_INCLUDE_DIRECTORIES", context,
- &dagChecker, entries, IncludeRuntimeInterface::Yes);
+ &dagChecker, entries, cm::IncludeRuntimeInterface::Yes);
processIncludeDirectories(this, entries, includes, uniqueIncludes,
debugIncludes);
diff --git a/Source/cmGeneratorTarget_LinkDirectories.cxx b/Source/cmGeneratorTarget_LinkDirectories.cxx
index 8f11a05..8f29794 100644
--- a/Source/cmGeneratorTarget_LinkDirectories.cxx
+++ b/Source/cmGeneratorTarget_LinkDirectories.cxx
@@ -30,12 +30,12 @@
namespace {
void processLinkDirectories(cmGeneratorTarget const* tgt,
- EvaluatedTargetPropertyEntries& entries,
+ cm::EvaluatedTargetPropertyEntries& entries,
std::vector<BT<std::string>>& directories,
std::unordered_set<std::string>& uniqueDirectories,
bool debugDirectories)
{
- for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
+ for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
cmLinkItem const& item = entry.LinkItem;
std::string const& targetName = item.AsStr();
@@ -135,11 +135,12 @@
this->DebugLinkDirectoriesDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->LinkDirectoriesEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->LinkDirectoriesEntries);
AddInterfaceEntries(this, "INTERFACE_LINK_DIRECTORIES", context, &dagChecker,
- entries, IncludeRuntimeInterface::Yes,
+ entries, cm::IncludeRuntimeInterface::Yes,
this->GetPolicyStatusCMP0099() == cmPolicies::NEW
? UseTo::Link
: UseTo::Compile);
diff --git a/Source/cmGeneratorTarget_Options.cxx b/Source/cmGeneratorTarget_Options.cxx
index 2244e46..2fee725 100644
--- a/Source/cmGeneratorTarget_Options.cxx
+++ b/Source/cmGeneratorTarget_Options.cxx
@@ -49,14 +49,14 @@
auto const DL_END = "</DEVICE_LINK>"_s;
void processOptions(cmGeneratorTarget const* tgt,
- EvaluatedTargetPropertyEntries const& entries,
+ cm::EvaluatedTargetPropertyEntries const& entries,
std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
bool debugOptions, char const* logName, OptionsParse parse,
bool processDeviceOptions = false)
{
bool splitOption = !processDeviceOptions;
- for (EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
+ for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
std::string usedOptions;
for (std::string const& opt : entry.Values) {
if (processDeviceOptions && (opt == DL_BEGIN || opt == DL_END)) {
@@ -222,7 +222,7 @@
MsvcCharSetInfo GetMsvcCharSetInfo(
cmGeneratorTarget const& tgt, std::string const& lang,
- EvaluatedTargetPropertyEntries const& entries)
+ cm::EvaluatedTargetPropertyEntries const& entries)
{
using MsvcCharSet = cmGeneratorTarget::MsvcCharSet;
@@ -235,7 +235,7 @@
return { MsvcCharSet::None, false };
}
- for (EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
+ for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
for (std::string const& value : entry.Values) {
MsvcCharSet charSet = cmGeneratorTarget::GetMsvcCharSet(value);
if (charSet != MsvcCharSet::None) {
@@ -289,11 +289,12 @@
this->DebugCompileOptionsDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->CompileOptionsEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->CompileOptionsEntries);
AddInterfaceEntries(this, "INTERFACE_COMPILE_OPTIONS", context, &dagChecker,
- entries, IncludeRuntimeInterface::Yes);
+ entries, cm::IncludeRuntimeInterface::Yes);
processOptions(this, entries, result, uniqueOptions, debugOptions,
"compile options", OptionsParse::Shell);
@@ -332,11 +333,12 @@
this->DebugCompileFeaturesDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->CompileFeaturesEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->CompileFeaturesEntries);
AddInterfaceEntries(this, "INTERFACE_COMPILE_FEATURES", context, &dagChecker,
- entries, IncludeRuntimeInterface::Yes);
+ entries, cm::IncludeRuntimeInterface::Yes);
processOptions(this, entries, result, uniqueFeatures, debugFeatures,
"compile features", OptionsParse::None);
@@ -382,11 +384,12 @@
this->DebugCompileDefinitionsDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->CompileDefinitionsEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->CompileDefinitionsEntries);
AddInterfaceEntries(this, "INTERFACE_COMPILE_DEFINITIONS", context,
- &dagChecker, entries, IncludeRuntimeInterface::Yes);
+ &dagChecker, entries, cm::IncludeRuntimeInterface::Yes);
// Add the character set definition
MsvcCharSetInfo charSetInfo = GetMsvcCharSetInfo(*this, language, entries);
@@ -449,11 +452,12 @@
this->DebugPrecompileHeadersDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->PrecompileHeadersEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->PrecompileHeadersEntries);
AddInterfaceEntries(this, "INTERFACE_PRECOMPILE_HEADERS", context,
- &dagChecker, entries, IncludeRuntimeInterface::Yes);
+ &dagChecker, entries, cm::IncludeRuntimeInterface::Yes);
std::vector<BT<std::string>> list;
processOptions(this, entries, list, uniqueOptions, debugDefines,
@@ -507,11 +511,12 @@
this->DebugLinkOptionsDone = true;
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->LinkOptionsEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->LinkOptionsEntries);
AddInterfaceEntries(this, "INTERFACE_LINK_OPTIONS", context, &dagChecker,
- entries, IncludeRuntimeInterface::Yes,
+ entries, cm::IncludeRuntimeInterface::Yes,
this->GetPolicyStatusCMP0099() == cmPolicies::NEW
? UseTo::Link
: UseTo::Compile);
@@ -684,12 +689,12 @@
this, "STATIC_LIBRARY_OPTIONS", nullptr, nullptr, context,
};
- EvaluatedTargetPropertyEntries entries;
+ cm::EvaluatedTargetPropertyEntries entries;
if (cmValue linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
std::unique_ptr<TargetPropertyEntry> entry = TargetPropertyEntry::Create(
*this->LocalGenerator->GetCMakeInstance(), *linkOptions);
entries.Entries.emplace_back(
- EvaluateTargetPropertyEntry(this, context, &dagChecker, *entry));
+ cm::EvaluateTargetPropertyEntry(this, context, &dagChecker, *entry));
}
processOptions(this, entries, result, uniqueOptions, false,
"static library link options", OptionsParse::Shell);
@@ -729,7 +734,7 @@
this, "LINK_DEPENDS", nullptr, nullptr, context,
};
- EvaluatedTargetPropertyEntries entries;
+ cm::EvaluatedTargetPropertyEntries entries;
if (cmValue linkDepends = this->GetProperty("LINK_DEPENDS")) {
cmList depends{ *linkDepends };
for (auto const& depend : depends) {
@@ -740,7 +745,7 @@
}
}
AddInterfaceEntries(this, "INTERFACE_LINK_DEPENDS", context, &dagChecker,
- entries, IncludeRuntimeInterface::Yes,
+ entries, cm::IncludeRuntimeInterface::Yes,
this->GetPolicyStatusCMP0099() == cmPolicies::NEW
? UseTo::Link
: UseTo::Compile);
diff --git a/Source/cmGeneratorTarget_Sources.cxx b/Source/cmGeneratorTarget_Sources.cxx
index 5278408..4a21427 100644
--- a/Source/cmGeneratorTarget_Sources.cxx
+++ b/Source/cmGeneratorTarget_Sources.cxx
@@ -4,7 +4,10 @@
#include "cmGeneratorTarget.h"
/* clang-format on */
+#include "cmConfigure.h"
+
#include <cstddef>
+#include <functional>
#include <map>
#include <memory>
#include <set>
@@ -16,15 +19,16 @@
#include <cm/string_view>
#include <cmext/algorithm>
-#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
#include "cmEvaluatedTargetProperty.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmList.h"
@@ -32,6 +36,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceGroup.h"
@@ -48,7 +53,7 @@
void AddObjectEntries(cmGeneratorTarget const* headTarget,
cm::GenEx::Context const& context,
cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries)
+ cm::EvaluatedTargetPropertyEntries& entries)
{
if (cmLinkImplementationLibraries const* impl =
headTarget->GetLinkImplementationLibraries(context.Config,
@@ -68,7 +73,7 @@
ge.Parse(std::move(genex));
cge->SetEvaluateForBuildsystem(true);
- EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ cm::EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
cmExpandList(cge->Evaluate(context, dagChecker, headTarget),
ee.Values);
if (cge->GetHadContextSensitiveCondition()) {
@@ -80,97 +85,29 @@
}
}
-void addFileSetEntry(cmGeneratorTarget const* headTarget,
- cm::GenEx::Context const& context,
- cmGeneratorExpressionDAGChecker* dagChecker,
- cmFileSet const* fileSet,
- EvaluatedTargetPropertyEntries& entries)
-{
- auto dirCges = fileSet->CompileDirectoryEntries();
- auto dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, headTarget,
- dagChecker);
- bool contextSensitiveDirs = false;
- for (auto const& dirCge : dirCges) {
- if (dirCge->GetHadContextSensitiveCondition()) {
- contextSensitiveDirs = true;
- break;
- }
- }
- cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance();
- for (auto& entryCge : fileSet->CompileFileEntries()) {
- auto targetPropEntry =
- cmGeneratorTarget::TargetPropertyEntry::CreateFileSet(
- dirs, contextSensitiveDirs, std::move(entryCge), fileSet);
- entries.Entries.emplace_back(EvaluateTargetPropertyEntry(
- headTarget, context, dagChecker, *targetPropEntry));
- EvaluatedTargetPropertyEntry const& entry = entries.Entries.back();
- for (auto const& file : entry.Values) {
- auto* sf = headTarget->Makefile->GetOrCreateSource(file);
- if (fileSet->GetType() == "HEADERS"_s) {
- sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
- }
-
-#ifndef CMAKE_BOOTSTRAP
- std::string e;
- std::string w;
- auto path = sf->ResolveFullPath(&e, &w);
- if (!w.empty()) {
- cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
- }
- if (path.empty()) {
- if (!e.empty()) {
- cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
- }
- return;
- }
- bool found = false;
- for (auto const& sg : headTarget->Makefile->GetSourceGroups()) {
- if (sg->MatchChildrenFiles(path)) {
- found = true;
- break;
- }
- }
- if (!found) {
- if (fileSet->GetType() == "HEADERS"_s) {
- headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
- ->AddGroupFile(path);
- }
- }
-#endif
- }
- }
-}
-
void AddFileSetEntries(cmGeneratorTarget const* headTarget,
+ cmGeneratorFileSets const* fileSets,
cm::GenEx::Context const& context,
cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries)
+ cm::EvaluatedTargetPropertyEntries& entries)
{
- for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) {
- for (auto const& name : cmList{ entry.Value }) {
- auto const* headerSet = headTarget->Target->GetFileSet(name);
- addFileSetEntry(headTarget, context, dagChecker, headerSet, entries);
- }
- }
- for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) {
- for (auto const& name : cmList{ entry.Value }) {
- auto const* cxxModuleSet = headTarget->Target->GetFileSet(name);
- addFileSetEntry(headTarget, context, dagChecker, cxxModuleSet, entries);
- }
- }
+ auto sources = fileSets->GetSources(context, headTarget, dagChecker);
+ entries =
+ EvaluateTargetPropertyEntries(headTarget, context, dagChecker, sources);
}
-bool processSources(cmGeneratorTarget const* tgt,
- EvaluatedTargetPropertyEntries& entries,
+bool processSources(cmGeneratorTarget const* tgt, std::string const& config,
+ cm::EvaluatedTargetPropertyEntries& entries,
std::vector<BT<std::string>>& srcs,
std::unordered_set<std::string>& uniqueSrcs,
- bool debugSources)
+ bool debugSources,
+ std::function<void(cmSourceFile*)> postProcess = {})
{
cmMakefile* mf = tgt->Target->GetMakefile();
bool contextDependent = entries.HadContextSensitiveCondition;
- for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
+ for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
if (entry.ContextDependent) {
contextDependent = true;
}
@@ -209,6 +146,10 @@
return contextDependent;
}
src = fullPath;
+
+ if (postProcess) {
+ postProcess(sf);
+ }
}
std::string usedSources;
for (std::string const& src : entry.Values) {
@@ -217,6 +158,28 @@
if (debugSources) {
usedSources += cmStrCat(" * ", src, '\n');
}
+ } else {
+ if (auto const* fileSet =
+ tgt->GetGeneratorFileSets()->GetFileSetForSource(config, src)) {
+ switch (tgt->GetPolicyStatusCMP0211()) {
+ case cmPolicies::WARN:
+ tgt->GetLocalGenerator()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0211),
+ "\nIn target \"", tgt->GetName(), "\" the file\n ",
+ src, "\nalready belongs to file set \"",
+ fileSet->GetName(), "\"."));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ default:
+ tgt->GetLocalGenerator()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("In target \"", tgt->GetName(), "\" the file\n ",
+ src, "\nalready belongs to file set \"",
+ fileSet->GetName(), "\"."));
+ }
+ }
}
}
if (!usedSources.empty()) {
@@ -250,28 +213,30 @@
this, "SOURCES", nullptr, nullptr, context,
};
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, context, &dagChecker, this->SourceEntries);
+ cm::EvaluatedTargetPropertyEntries entries =
+ cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
+ this->SourceEntries);
std::unordered_set<std::string> uniqueSrcs;
bool contextDependentDirectSources =
- processSources(this, entries, files, uniqueSrcs, debugSources);
+ processSources(this, config, entries, files, uniqueSrcs, debugSources);
// Collect INTERFACE_SOURCES of all direct link-dependencies.
- EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
- AddInterfaceEntries(this, "INTERFACE_SOURCES", context, &dagChecker,
- linkInterfaceSourcesEntries, IncludeRuntimeInterface::No,
- UseTo::Compile);
- bool contextDependentInterfaceSources = processSources(
- this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
+ cm::EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
+ cm::AddInterfaceEntries(this, "INTERFACE_SOURCES", context, &dagChecker,
+ linkInterfaceSourcesEntries,
+ cm::IncludeRuntimeInterface::No, UseTo::Compile);
+ bool contextDependentInterfaceSources =
+ processSources(this, config, linkInterfaceSourcesEntries, files,
+ uniqueSrcs, debugSources);
// Collect TARGET_OBJECTS of direct object link-dependencies.
bool contextDependentObjects = false;
if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- EvaluatedTargetPropertyEntries linkObjectsEntries;
+ cm::EvaluatedTargetPropertyEntries linkObjectsEntries;
AddObjectEntries(this, context, &dagChecker, linkObjectsEntries);
- contextDependentObjects = processSources(this, linkObjectsEntries, files,
- uniqueSrcs, debugSources);
+ contextDependentObjects = processSources(this, config, linkObjectsEntries,
+ files, uniqueSrcs, debugSources);
// Note that for imported targets or multi-config generators supporting
// cross-config builds the paths to the object files must be per-config,
// so contextDependentObjects will be true here even if object libraries
@@ -279,14 +244,52 @@
}
// Collect this target's file sets.
- EvaluatedTargetPropertyEntries fileSetEntries;
- AddFileSetEntries(this, context, &dagChecker, fileSetEntries);
+ cmGeneratorExpressionDAGChecker fsDagChecker{
+ this, "SOURCES", nullptr, nullptr, context,
+ };
+
+ cm::EvaluatedTargetPropertyEntries fileSetEntries;
+ AddFileSetEntries(this, this->FileSets.get(), context, &fsDagChecker,
+ fileSetEntries);
+ auto processFileSetEntry = [this, &config](cmSourceFile* sf) {
+ auto const* fileSet = this->GetFileSetForSource(config, sf);
+ if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
+ sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
+ }
+#if !defined(CMAKE_BOOTSTRAP)
+ cmMakefile* mf = this->Target->GetMakefile();
+ auto const& path = sf->GetFullPath();
+ bool found = false;
+ for (auto const& sg : mf->GetSourceGroups()) {
+ if (sg->MatchChildrenFiles(path)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
+ mf->GetOrCreateSourceGroup("Header Files")->AddGroupFile(path);
+ }
+ }
+#endif
+ };
bool contextDependentFileSets =
- processSources(this, fileSetEntries, files, uniqueSrcs, debugSources);
+ processSources(this, config, fileSetEntries, files, uniqueSrcs,
+ debugSources, processFileSetEntry);
+
+ // Collect file sets INTERFACE_SOURCES of all direct link-dependencies.
+ cm::EvaluatedTargetPropertyEntries linkInterfaceFileSetsEntries;
+ cm::AddInterfaceFileSetsEntries(this, cm::FileSetMetadata::SOURCES,
+ "INTERFACE_SOURCES", context, &fsDagChecker,
+ linkInterfaceFileSetsEntries);
+ bool contextDependentInterfaceFileSets =
+ processSources(this, config, linkInterfaceFileSetsEntries, files,
+ uniqueSrcs, debugSources);
// Determine if sources are context-dependent or not.
if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
- !contextDependentObjects && !contextDependentFileSets) {
+ !contextDependentObjects && !contextDependentFileSets &&
+ !contextDependentInterfaceFileSets) {
this->SourcesAreContextDependent = Tribool::False;
} else {
this->SourcesAreContextDependent = Tribool::True;
@@ -385,6 +388,12 @@
cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
std::vector<cmSourceFile*> badObjLib;
+ cmValue const rustMainCrateRootProp =
+ this->GetProperty("Rust_MAIN_CRATE_ROOT");
+ cmSourceFile const* rustMainCrateRootSf = rustMainCrateRootProp
+ ? this->Makefile->GetOrCreateSource(rustMainCrateRootProp)
+ : nullptr;
+
std::set<cmSourceFile*> emitted;
for (BT<std::string> const& s : srcs) {
// Create each source at most once.
@@ -396,11 +405,11 @@
// Compute the kind (classification) of this source file.
SourceKind kind;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- cmFileSet const* fs = this->GetFileSetForSource(config, sf);
+ cmGeneratorFileSet const* fs = this->GetFileSetForSource(config, sf);
if (sf->GetCustomCommand()) {
kind = SourceKindCustomCommand;
} else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
- fs && (fs->GetType() == "CXX_MODULES"_s)) {
+ fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) {
kind = SourceKindCxxModuleSource;
} else if (this->Target->GetType() == cmStateEnums::UTILITY ||
this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
@@ -417,7 +426,28 @@
} else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
kind = SourceKindExternalObject;
} else if (!sf->GetOrDetermineLanguage().empty()) {
- kind = SourceKindObjectSource;
+ if (sf->GetOrDetermineLanguage() == "Rust") {
+ // NOLINTNEXTLINE(bugprone-branch-clone)
+ if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // There is no main crate root for object libraries.
+ kind = SourceKindObjectSource;
+ } else if (!rustMainCrateRootSf) {
+ // We do not have a main crate root source file, we use the first
+ // Rust source file for it.
+ rustMainCrateRootSf = sf;
+ kind = SourceKindRustMainCrateRoot;
+ } else if (rustMainCrateRootSf == sf) {
+ // Current source file is the main crate root defined in the target
+ // Rust_MAIN_CRATE_ROOT property.
+ kind = SourceKindRustMainCrateRoot;
+ } else {
+ // Any other Rust source file is treated as a normal object, but will
+ // be built into a .rlib. Maybe in the future this could be changed?
+ kind = SourceKindObjectSource;
+ }
+ } else {
+ kind = SourceKindObjectSource;
+ }
} else if (ext == "def") {
kind = SourceKindModuleDefinition;
if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
diff --git a/Source/cmGeneratorTarget_TargetPropertyEntry.cxx b/Source/cmGeneratorTarget_TargetPropertyEntry.cxx
deleted file mode 100644
index 2280e93..0000000
--- a/Source/cmGeneratorTarget_TargetPropertyEntry.cxx
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file LICENSE.rst or https://cmake.org/licensing for details. */
-/* clang-format off */
-#include "cmGeneratorTarget.h"
-/* clang-format on */
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <cm/memory>
-
-#include "cmFileSet.h"
-#include "cmGeneratorExpression.h"
-#include "cmLinkItem.h"
-#include "cmList.h"
-#include "cmListFileCache.h"
-
-class cmake;
-
-cmLinkItem cmGeneratorTarget::TargetPropertyEntry::NoLinkItem;
-
-class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
-{
-public:
- TargetPropertyEntryString(BT<std::string> propertyValue,
- cmLinkItem const& item = NoLinkItem)
- : cmGeneratorTarget::TargetPropertyEntry(item)
- , PropertyValue(std::move(propertyValue))
- {
- }
-
- std::string const& Evaluate(cm::GenEx::Context const&,
- cmGeneratorTarget const*,
- cmGeneratorExpressionDAGChecker*) const override
- {
- return this->PropertyValue.Value;
- }
-
- cmListFileBacktrace GetBacktrace() const override
- {
- return this->PropertyValue.Backtrace;
- }
- std::string const& GetInput() const override
- {
- return this->PropertyValue.Value;
- }
-
-private:
- BT<std::string> PropertyValue;
-};
-
-class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry
-{
-public:
- TargetPropertyEntryGenex(std::unique_ptr<cmCompiledGeneratorExpression> cge,
- cmLinkItem const& item = NoLinkItem)
- : cmGeneratorTarget::TargetPropertyEntry(item)
- , ge(std::move(cge))
- {
- }
-
- std::string const& Evaluate(
- cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker) const override
- {
- return this->ge->Evaluate(context, dagChecker, headTarget);
- }
-
- cmListFileBacktrace GetBacktrace() const override
- {
- return this->ge->GetBacktrace();
- }
-
- std::string const& GetInput() const override { return this->ge->GetInput(); }
-
- bool GetHadContextSensitiveCondition() const override
- {
- return this->ge->GetHadContextSensitiveCondition();
- }
-
-private:
- std::unique_ptr<cmCompiledGeneratorExpression> const ge;
-};
-
-class TargetPropertyEntryFileSet
- : public cmGeneratorTarget::TargetPropertyEntry
-{
-public:
- TargetPropertyEntryFileSet(
- std::vector<std::string> dirs, bool contextSensitiveDirs,
- std::unique_ptr<cmCompiledGeneratorExpression> entryCge,
- cmFileSet const* fileSet, cmLinkItem const& item = NoLinkItem)
- : cmGeneratorTarget::TargetPropertyEntry(item)
- , BaseDirs(std::move(dirs))
- , ContextSensitiveDirs(contextSensitiveDirs)
- , EntryCge(std::move(entryCge))
- , FileSet(fileSet)
- {
- }
-
- std::string const& Evaluate(
- cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker) const override
- {
- std::map<std::string, std::vector<std::string>> filesPerDir;
- this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir,
- this->EntryCge, context, headTarget,
- dagChecker);
-
- std::vector<std::string> files;
- for (auto const& it : filesPerDir) {
- files.insert(files.end(), it.second.begin(), it.second.end());
- }
-
- static std::string filesStr;
- filesStr = cmList::to_string(files);
- return filesStr;
- }
-
- cmListFileBacktrace GetBacktrace() const override
- {
- return this->EntryCge->GetBacktrace();
- }
-
- std::string const& GetInput() const override
- {
- return this->EntryCge->GetInput();
- }
-
- bool GetHadContextSensitiveCondition() const override
- {
- return this->ContextSensitiveDirs ||
- this->EntryCge->GetHadContextSensitiveCondition();
- }
-
-private:
- std::vector<std::string> const BaseDirs;
- bool const ContextSensitiveDirs;
- std::unique_ptr<cmCompiledGeneratorExpression> const EntryCge;
- cmFileSet const* FileSet;
-};
-
-std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>
-cmGeneratorTarget::TargetPropertyEntry::Create(
- cmake& cmakeInstance, const BT<std::string>& propertyValue,
- bool evaluateForBuildsystem)
-{
- if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) {
- cmGeneratorExpression ge(cmakeInstance, propertyValue.Backtrace);
- std::unique_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(propertyValue.Value);
- cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
- return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
- cm::make_unique<TargetPropertyEntryGenex>(std::move(cge)));
- }
-
- return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
- cm::make_unique<TargetPropertyEntryString>(propertyValue));
-}
-
-std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>
-cmGeneratorTarget::TargetPropertyEntry::CreateFileSet(
- std::vector<std::string> dirs, bool contextSensitiveDirs,
- std::unique_ptr<cmCompiledGeneratorExpression> entryCge,
- cmFileSet const* fileSet, cmLinkItem const& item)
-{
- return cm::make_unique<TargetPropertyEntryFileSet>(
- std::move(dirs), contextSensitiveDirs, std::move(entryCge), fileSet, item);
-}
-
-cmGeneratorTarget::TargetPropertyEntry::TargetPropertyEntry(
- cmLinkItem const& item)
- : LinkItem(item)
-{
-}
-
-bool cmGeneratorTarget::TargetPropertyEntry::GetHadContextSensitiveCondition()
- const
-{
- return false;
-}
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 16e68fd..9c08298 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -10,15 +10,19 @@
#include <vector>
#include <cm/optional>
+#include <cmext/string_view>
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGhsMultiGenerator.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmList.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
@@ -503,6 +507,34 @@
}
}
+void cmGhsMultiTargetGenerator::WriteFileSetProperty(
+ std::ostream& fout, cmGeneratorFileSet const* fileSet,
+ std::string const& lang, cm::string_view propName, cm::string_view propFlag)
+{
+ if (!fileSet) {
+ return;
+ }
+
+ std::vector<BT<std::string>> entries;
+ if (propName == "COMPILE_OPTIONS"_s) {
+ entries = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileOptions(this->ConfigName, lang)
+ : fileSet->GetInterfaceCompileOptions(this->ConfigName, lang);
+ } else if (propName == "COMPILE_DEFINITIONS"_s) {
+ entries = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileDefinitions(this->ConfigName, lang)
+ : fileSet->GetInterfaceCompileDefinitions(this->ConfigName, lang);
+ } else if (propName == "INCLUDE_DIRECTORIES"_s) {
+ entries = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetIncludeDirectories(this->ConfigName, lang)
+ : fileSet->GetInterfaceIncludeDirectories(this->ConfigName, lang);
+ }
+
+ for (auto const& entry : entries) {
+ fout << " " << propFlag << entry.Value << '\n';
+ }
+}
+
void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
{
/* vector of all sources for this target */
@@ -642,9 +674,20 @@
*fout << comment << fname << WriteObjectLangOverride(si) << '\n';
if (compile) {
+ // lookup for the associated file set, if any.
+ auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ this->ConfigName, si);
+
+ this->WriteFileSetProperty(*fout, fileSet, si->GetLanguage(),
+ "INCLUDE_DIRECTORIES"_s, "");
this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
+ this->WriteFileSetProperty(*fout, fileSet, si->GetLanguage(),
+ "COMPILE_DEFINITIONS"_s, "");
this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
+ this->WriteFileSetProperty(*fout, fileSet, si->GetLanguage(),
+ "COMPILE_OPTIONS"_s, "");
/* to avoid clutter in the GUI only print out the objectName if it
* has been renamed */
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
index 91ca105..fa07103 100644
--- a/Source/cmGhsMultiTargetGenerator.h
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmGhsMultiGpj.h"
class cmCustomCommand;
@@ -17,6 +19,7 @@
class cmLocalGhsMultiGenerator;
class cmMakefile;
class cmSourceFile;
+class cmGeneratorFileSet;
class cmGhsMultiTargetGenerator
{
@@ -65,6 +68,10 @@
void WriteSourceProperty(std::ostream& fout, cmSourceFile const* sf,
std::string const& propName,
std::string const& propFlag);
+ void WriteFileSetProperty(std::ostream& fout,
+ cmGeneratorFileSet const* fileSet,
+ std::string const& lang, cm::string_view propName,
+ cm::string_view propFlag);
static std::string WriteObjectLangOverride(cmSourceFile const* sourceFile);
bool DetermineIfIntegrityApp();
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index e4f50d3..0a36d67 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1086,6 +1086,13 @@
{
std::string const& lang = source.GetLanguage();
if (!lang.empty()) {
+ if (lang == "Rust") {
+ // Rust source file can be compiled into different type of outputs. So
+ // we need to change the extension based on the Rust_EMIT property.
+ if (cmValue const rustEmit = source.GetRustEmitProperty()) {
+ return this->GetRustEmitOutputExtension(rustEmit);
+ }
+ }
return this->GetLanguageOutputExtension(lang);
}
// if no language is found then check to see if it is already an
@@ -1110,6 +1117,16 @@
return "";
}
+std::string cmGlobalGenerator::GetRustEmitOutputExtension(
+ std::string const& emitValue) const
+{
+ auto const it = this->RustEmitToOutputExtension.find(emitValue);
+ if (it != this->RustEmitToOutputExtension.end()) {
+ return it->second;
+ }
+ return "";
+}
+
cm::string_view cmGlobalGenerator::GetLanguageFromExtension(
cm::string_view ext) const
{
@@ -1210,6 +1227,19 @@
}
}
+ if (l == "Rust") {
+ std::string const emitValues =
+ mf->GetSafeDefinition("CMAKE_Rust_EMIT_VALUES");
+ cmList emitList{ emitValues };
+ for (std::string const& v : emitList) {
+ std::string emitOutputExtension =
+ cmStrCat("CMAKE_Rust_EMIT_", v, "_OUTPUT_EXTENSION");
+ if (cmValue outputExtension = mf->GetDefinition(emitOutputExtension)) {
+ this->RustEmitToOutputExtension[v] = outputExtension;
+ }
+ }
+ }
+
// The map was originally filled by SetLanguageEnabledFlag, but
// since then the compiler- and platform-specific files have been
// loaded which might have added more entries.
@@ -3697,8 +3727,8 @@
if (d.Load(dir)) {
unsigned long n = d.GetNumberOfFiles();
for (unsigned long i = 0; i < n; ++i) {
- char const* f = d.GetFile(i);
- if (strcmp(f, ".") != 0 && strcmp(f, "..") != 0) {
+ std::string const& f = d.GetFileName(i);
+ if (f != "." && f != "..") {
dc.All.insert(f);
}
}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 7e6e4b4..3c11699 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -369,6 +369,8 @@
std::string GetLanguageOutputExtension(cmSourceFile const&) const;
//! What is the object file extension for a given language?
std::string GetLanguageOutputExtension(std::string const& lang) const;
+ //! What is the object file extension for a given --emit option in Rust?
+ std::string GetRustEmitOutputExtension(std::string const& emitValue) const;
//! What is the configurations directory variable called?
virtual char const* GetCMakeCFGIntDir() const { return "."; }
@@ -875,6 +877,7 @@
std::set<std::string> LanguagesInProgress;
std::map<std::string, std::string> OutputExtensions;
std::map<std::string, std::string> LanguageToOutputExtension;
+ std::map<std::string, std::string> RustEmitToOutputExtension;
#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
std::map<std::string, std::string, std::less<void>> ExtensionToLanguage;
#else
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index e6687ce..2ff9b93 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmGlobalMinGWMakefileGenerator.h"
-#include "cmMakefile.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmake.h"
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index b145641..dfac9ff 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -43,6 +43,7 @@
#include "cmOutputConverter.h"
#include "cmRange.h"
#include "cmScanDepFormat.h"
+#include "cmScriptGenerator.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -1382,17 +1383,18 @@
std::string const& targetConfig) {
if (depTarget->CanCompileSources()) {
auto headers = depTarget->GetGeneratedISPCHeaders(targetConfig);
+ auto const mapToNinjaPath = gg->MapToNinjaPath();
if (!headers.empty()) {
std::transform(headers.begin(), headers.end(), headers.begin(),
- gg->MapToNinjaPath());
+ mapToNinjaPath);
outputDeps.insert(outputDeps.end(), headers.begin(), headers.end());
}
auto objs = depTarget->GetGeneratedISPCObjects(targetConfig);
- if (!objs.empty()) {
- std::transform(objs.begin(), objs.end(), objs.begin(),
- gg->MapToNinjaPath());
- outputDeps.insert(outputDeps.end(), objs.begin(), objs.end());
- }
+ std::transform(
+ objs.begin(), objs.end(), std::back_inserter(outputDeps),
+ [&mapToNinjaPath](
+ std::pair<cmSourceFile const*, std::string> const& obj)
+ -> std::string { return mapToNinjaPath(obj.second); });
}
};
@@ -2030,8 +2032,7 @@
fout << " file(REMOVE_RECURSE\n";
for (std::string const& acf : it->second.AdditionalCleanFiles) {
fout << " "
- << cmOutputConverter::EscapeForCMake(
- this->ConvertToNinjaPath(acf))
+ << cmScriptGenerator::Quote(this->ConvertToNinjaPath(acf))
<< '\n';
}
fout << " )\n";
@@ -2587,8 +2588,8 @@
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
std::vector<std::string> const& forward_modules_from_target_dirs,
- std::string const& arg_lang, std::string const& arg_modmapfmt,
- cmCxxModuleExportInfo const& export_info)
+ std::string const& native_target_dir, std::string const& arg_lang,
+ std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info)
{
// Setup path conversions.
{
@@ -2748,6 +2749,47 @@
}
}
+ // If this is a synthetic target for a non-imported target, read PRIVATE
+ // module info from the native target
+ if (!native_target_dir.empty()) {
+ std::string const modules_info_path =
+ cmStrCat(native_target_dir, '/', arg_lang, "Modules.json");
+ Json::Value native_modules_info;
+ cmsys::ifstream modules_file(modules_info_path.c_str(),
+ std::ios::in | std::ios::binary);
+ if (!modules_file) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to open ",
+ modules_info_path,
+ " for module information"));
+ return false;
+ }
+ Json::Reader reader;
+ if (!reader.parse(modules_file, native_modules_info, false)) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ modules_info_path,
+ reader.getFormattedErrorMessages()));
+ return false;
+ }
+ if (native_modules_info.isObject()) {
+ Json::Value const& native_target_modules =
+ native_modules_info["modules"];
+ if (native_target_modules.isObject()) {
+ for (auto i = native_target_modules.begin();
+ i != native_target_modules.end(); ++i) {
+ Json::Value const& visible_module = *i;
+ if (visible_module.isObject()) {
+ auto is_private = visible_module["is-private"].asBool();
+ // Only add private modules since others are discovered by the
+ // synthetic target's own scan rules
+ if (is_private) {
+ target_modules[i.key().asString()] = visible_module;
+ }
+ }
+ }
+ }
+ }
+ }
+
cmGeneratedFileStream ddf(arg_dd);
ddf << "ninja_dyndep_version = 1.0\n";
@@ -3041,6 +3083,7 @@
tdi_forward_modules_from_target_dir.asString());
}
}
+ std::string const native_target_dir = tdi["native-target-dir"].asString();
std::string const compilerId = tdi["compiler-id"].asString();
std::string const simulateId = tdi["compiler-simulate-id"].asString();
std::string const compilerFrontendVariant =
@@ -3064,8 +3107,9 @@
# endif
return gg.WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld,
arg_dd, arg_ddis, module_dir, linked_target_dirs,
- forward_modules_from_target_dirs, arg_lang,
- arg_modmapfmt, *export_info)
+ forward_modules_from_target_dirs,
+ native_target_dir, arg_lang, arg_modmapfmt,
+ *export_info)
? 0
: 1;
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 152c45c..059dea8 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -433,7 +433,8 @@
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
std::vector<std::string> const& forward_modules_from_target_dirs,
- std::string const& arg_lang, std::string const& arg_modmapfmt,
+ std::string const& native_target_dir, std::string const& arg_lang,
+ std::string const& arg_modmapfmt,
cmCxxModuleExportInfo const& export_info);
virtual std::string BuildAlias(std::string const& alias,
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index bd0a3e8..cbc6dde 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -19,8 +19,6 @@
#include "cmsys/RegularExpression.hxx"
#include "cmCryptoHash.h"
-#include "cmDocumentationEntry.h"
-#include "cmExperimental.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudio7Generator.h"
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index ec6702b..88c83e6 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -14,7 +14,6 @@
#include <windows.h>
#include "cmGeneratedFileStream.h"
-#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
@@ -22,7 +21,6 @@
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 68614bb..1c7fc47 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -28,6 +28,8 @@
#include "cmCustomCommandTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGeneratorFactory.h"
@@ -1091,6 +1093,12 @@
break;
}
+ // lookup for the associated file set, if any.
+ //// sources are independent of the config but needed here
+ auto const& config = this->CurrentConfigurationTypes[0];
+ auto const* fileSet =
+ gtgt->GetGeneratorFileSets()->GetFileSetForSource(config, sf);
+
// Explicitly add the explicit language flag before any other flag
// so user flags can override it.
gtgt->AddExplicitLanguageFlags(flags, *sf);
@@ -1104,6 +1112,15 @@
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
}
+ // Add flags from file set properties.
+ if (fileSet) {
+ auto options = fileSet->BelongsTo(gtgt)
+ ? fileSet->GetCompileOptions(config, lang)
+ : fileSet->GetInterfaceCompileOptions(config, lang);
+ if (!options.empty()) {
+ lg->AppendCompileOptions(flags, cm::remove_BT(options));
+ }
+ }
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
@@ -1114,6 +1131,15 @@
genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS).c_str(),
true);
}
+ // Add file set preprocessor definitions
+ if (fileSet) {
+ auto fsDefines = fileSet->BelongsTo(gtgt)
+ ? fileSet->GetCompileDefinitions(config, lang)
+ : fileSet->GetInterfaceCompileDefinitions(config, lang);
+ if (!fsDefines.empty()) {
+ this->AppendDefines(flagsBuild, cm::remove_BT(fsDefines), true);
+ }
+ }
if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true);
@@ -1126,8 +1152,17 @@
flags += flagsBuild.GetString();
}
- // Add per-source include directories.
std::vector<std::string> includes;
+ // Add include directories from file set properties.
+ if (fileSet) {
+ auto fsIncludes = fileSet->BelongsTo(gtgt)
+ ? fileSet->GetIncludeDirectories(config, lang)
+ : fileSet->GetInterfaceIncludeDirectories(config, lang);
+ if (!fsIncludes.empty()) {
+ lg->AppendIncludeDirectories(includes, cm::remove_BT(fsIncludes), *sf);
+ }
+ }
+ // Add per-source include directories.
std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (cmValue cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
lg->AppendIncludeDirectories(
@@ -2095,7 +2130,8 @@
realDepends.reserve(ccg.GetDepends().size());
for (auto const& d : ccg.GetDepends()) {
std::string dep;
- if (this->CurrentLocalGenerator->GetRealDependency(d, configName, dep)) {
+ if (this->CurrentLocalGenerator->GetRealDependency(
+ d, configName, dep, cc.GetCMP0212Status())) {
realDepends.emplace_back(std::move(dep));
}
}
@@ -2464,7 +2500,8 @@
realDepends.reserve(ccg.GetDepends().size());
for (auto const& d : ccg.GetDepends()) {
std::string dep;
- if (this->CurrentLocalGenerator->GetRealDependency(d, configName, dep)) {
+ if (this->CurrentLocalGenerator->GetRealDependency(
+ d, configName, dep, command.GetCMP0212Status())) {
realDepends.emplace_back(std::move(dep));
}
}
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index e9d9e15..84a7034 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -48,7 +48,8 @@
}
bool optional = false;
- bool noPolicyScope = false;
+ cm::PolicyScope policyScope = cm::PolicyScope::Local;
+ cm::DiagnosticScope diagnosticScope = cm::DiagnosticScope::Local;
std::string fname = args[0];
std::string resultVarName;
@@ -72,7 +73,9 @@
return false;
}
} else if (args[i] == "NO_POLICY_SCOPE") {
- noPolicyScope = true;
+ policyScope = cm::PolicyScope::None;
+ } else if (args[i] == "NO_DIAGNOSTIC_SCOPE") {
+ diagnosticScope = cm::DiagnosticScope::None;
} else if (i > 1) // compat.: in previous cmake versions the second
// parameter was ignored if it wasn't "OPTIONAL"
{
@@ -161,8 +164,8 @@
}
}
- bool readit =
- status.GetMakefile().ReadDependentFile(listFile, noPolicyScope);
+ bool const readit = status.GetMakefile().ReadDependentFile(
+ listFile, policyScope, diagnosticScope);
// add the location of the included file if a result variable was given
if (!resultVarName.empty()) {
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 1d37546..1783e18 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -31,6 +31,7 @@
#include "cmInstallCommandArguments.h"
#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
+#include "cmInstallDirs.h"
#include "cmInstallFileSetGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
@@ -94,6 +95,14 @@
{
this->DefaultComponentName = this->Makefile->GetSafeDefinition(
"CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+ if (this->DefaultComponentName == "<PROJECT_NAME>") {
+ cmValue projectName = this->Makefile->GetDefinition("PROJECT_NAME");
+ if (!projectName->empty()) {
+ this->DefaultComponentName = projectName;
+ } else {
+ this->DefaultComponentName = "Unspecified";
+ }
+ }
if (this->DefaultComponentName.empty()) {
this->DefaultComponentName = "Unspecified";
}
@@ -108,12 +117,8 @@
std::vector<std::string> const& relFiles,
std::vector<std::string>& absFiles);
- std::string GetDestination(cmInstallCommandArguments const* args,
- std::string const& varName,
- std::string const& guess) const;
std::string GetRuntimeDestination(
cmInstallCommandArguments const* args) const;
- std::string GetSbinDestination(cmInstallCommandArguments const* args) const;
std::string GetArchiveDestination(
cmInstallCommandArguments const* args) const;
std::string GetLibraryDestination(
@@ -122,24 +127,6 @@
cmInstallCommandArguments const* args) const;
std::string GetIncludeDestination(
cmInstallCommandArguments const* args) const;
- std::string GetSysconfDestination(
- cmInstallCommandArguments const* args) const;
- std::string GetSharedStateDestination(
- cmInstallCommandArguments const* args) const;
- std::string GetLocalStateDestination(
- cmInstallCommandArguments const* args) const;
- std::string GetRunStateDestination(
- cmInstallCommandArguments const* args) const;
- std::string GetDataRootDestination(
- cmInstallCommandArguments const* args) const;
- std::string GetDataDestination(cmInstallCommandArguments const* args) const;
- std::string GetInfoDestination(cmInstallCommandArguments const* args) const;
- std::string GetLocaleDestination(
- cmInstallCommandArguments const* args) const;
- std::string GetManDestination(cmInstallCommandArguments const* args) const;
- std::string GetDocDestination(cmInstallCommandArguments const* args) const;
- std::string GetProgramExecutablesDestination(
- cmInstallCommandArguments const* args) const;
std::string GetDestinationForType(cmInstallCommandArguments const* args,
std::string const& type) const;
@@ -199,13 +186,13 @@
}
std::unique_ptr<cmInstallFileSetGenerator> CreateInstallFileSetGenerator(
- Helper& helper, cmTarget& target, cmFileSetDestinations dests,
+ Helper& helper, cmTarget& target,
cmInstallCommandFileSetArguments const& args)
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(helper.Makefile);
return cm::make_unique<cmInstallFileSetGenerator>(
- target.GetName(), args.GetFileSet(), std::move(dests),
+ target.GetName(), args.GetFileSet(), args.GetDestination(),
args.GetPermissions(), args.GetConfigurations(), args.GetComponent(),
message, args.GetExcludeFromAll(), args.GetOptional(),
helper.Makefile->GetBacktrace());
@@ -1147,11 +1134,8 @@
if (!namelinkOnly) {
for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
- cmFileSetDestinations dests;
- dests.Headers = helper.GetIncludeDestination(&fileSetArgs[i]);
- dests.CXXModules = fileSetArgs[i].GetDestination();
- fileSetGenerators.push_back(CreateInstallFileSetGenerator(
- helper, target, std::move(dests), fileSetArgs[i]));
+ fileSetGenerators.push_back(
+ CreateInstallFileSetGenerator(helper, target, fileSetArgs[i]));
installsFileSet[i] = true;
}
}
@@ -2626,42 +2610,31 @@
return true;
}
-std::string Helper::GetDestination(cmInstallCommandArguments const* args,
- std::string const& varName,
- std::string const& guess) const
+std::string Helper::GetRuntimeDestination(
+ cmInstallCommandArguments const* args) const
{
if (args && !args->GetDestination().empty()) {
return args->GetDestination();
}
- std::string val = this->Makefile->GetSafeDefinition(varName);
- if (!val.empty()) {
- return val;
- }
- return guess;
-}
-
-std::string Helper::GetRuntimeDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
-}
-
-std::string Helper::GetSbinDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
+ return cm::InstallDirs::GetRuntimeDirectory(this->Makefile);
}
std::string Helper::GetArchiveDestination(
cmInstallCommandArguments const* args) const
{
- return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ return cm::InstallDirs::GetArchiveDirectory(this->Makefile);
}
std::string Helper::GetLibraryDestination(
cmInstallCommandArguments const* args) const
{
- return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ return cm::InstallDirs::GetLibraryDirectory(this->Makefile);
}
std::string Helper::GetCxxModulesBmiDestination(
@@ -2676,81 +2649,10 @@
std::string Helper::GetIncludeDestination(
cmInstallCommandArguments const* args) const
{
- return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
-}
-
-std::string Helper::GetSysconfDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
-}
-
-std::string Helper::GetSharedStateDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
-}
-
-std::string Helper::GetLocalStateDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
-}
-
-std::string Helper::GetRunStateDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
- this->GetLocalStateDestination(nullptr) +
- "/run");
-}
-
-std::string Helper::GetDataRootDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
-}
-
-std::string Helper::GetDataDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
- this->GetDataRootDestination(nullptr));
-}
-
-std::string Helper::GetInfoDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
- this->GetDataRootDestination(nullptr) + "/info");
-}
-
-std::string Helper::GetLocaleDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
- this->GetDataRootDestination(nullptr) +
- "/locale");
-}
-
-std::string Helper::GetManDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
- this->GetDataRootDestination(nullptr) + "/man");
-}
-
-std::string Helper::GetDocDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
- this->GetDataRootDestination(nullptr) + "/doc");
-}
-
-std::string Helper::GetProgramExecutablesDestination(
- cmInstallCommandArguments const* args) const
-{
- return this->GetDestination(args, "CMAKE_INSTALL_LIBEXECDIR", "libexec");
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ return cm::InstallDirs::GetIncludeDirectory(this->Makefile);
}
std::string Helper::GetDestinationForType(
@@ -2759,49 +2661,7 @@
if (args && !args->GetDestination().empty()) {
return args->GetDestination();
}
- if (type == "BIN") {
- return this->GetRuntimeDestination(nullptr);
- }
- if (type == "SBIN") {
- return this->GetSbinDestination(nullptr);
- }
- if (type == "SYSCONF") {
- return this->GetSysconfDestination(nullptr);
- }
- if (type == "SHAREDSTATE") {
- return this->GetSharedStateDestination(nullptr);
- }
- if (type == "LOCALSTATE") {
- return this->GetLocalStateDestination(nullptr);
- }
- if (type == "RUNSTATE") {
- return this->GetRunStateDestination(nullptr);
- }
- if (type == "LIB") {
- return this->GetLibraryDestination(nullptr);
- }
- if (type == "INCLUDE") {
- return this->GetIncludeDestination(nullptr);
- }
- if (type == "DATA") {
- return this->GetDataDestination(nullptr);
- }
- if (type == "INFO") {
- return this->GetInfoDestination(nullptr);
- }
- if (type == "LOCALE") {
- return this->GetLocaleDestination(nullptr);
- }
- if (type == "MAN") {
- return this->GetManDestination(nullptr);
- }
- if (type == "DOC") {
- return this->GetDocDestination(nullptr);
- }
- if (type == "LIBEXEC") {
- return this->GetProgramExecutablesDestination(nullptr);
- }
- return "";
+ return cm::InstallDirs::GetDirectoryForType(this->Makefile, type);
}
} // namespace
diff --git a/Source/cmInstallCxxModuleBmiGenerator.cxx b/Source/cmInstallCxxModuleBmiGenerator.cxx
index 5f7ea52..66f39a4 100644
--- a/Source/cmInstallCxxModuleBmiGenerator.cxx
+++ b/Source/cmInstallCxxModuleBmiGenerator.cxx
@@ -10,7 +10,6 @@
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
-#include "cmOutputConverter.h"
#include "cmScriptGenerator.h"
#include "cmStringAlgorithms.h"
@@ -69,8 +68,6 @@
if (loc.empty()) {
return;
}
- os << indent << "include(\""
- << cmOutputConverter::EscapeForCMake(
- loc, cmOutputConverter::WrapQuotes::NoWrap)
- << "\" OPTIONAL)\n";
+ os << indent << "include(" << cmScriptGenerator::Quote(loc)
+ << " OPTIONAL)\n";
}
diff --git a/Source/cmInstallDirs.cxx b/Source/cmInstallDirs.cxx
new file mode 100644
index 0000000..0c17bc2
--- /dev/null
+++ b/Source/cmInstallDirs.cxx
@@ -0,0 +1,160 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#include "cmInstallDirs.h"
+
+#include <cmext/string_view>
+
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmValue.h"
+
+namespace {
+std::string GetDirectory(cmMakefile const* makefile,
+ std::string const& varName, std::string const& guess)
+{
+ cmValue value = makefile->GetDefinition(varName);
+ if (!value.IsEmpty()) {
+ return value;
+ }
+ return guess;
+}
+} // namespace
+
+namespace cm {
+namespace InstallDirs {
+std::string GetRuntimeDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_BINDIR", "bin");
+}
+
+std::string GetSbinDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_SBINDIR", "sbin");
+}
+
+std::string GetArchiveDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string GetLibraryDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string GetIncludeDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_INCLUDEDIR", "include");
+}
+
+std::string GetSysconfDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_SYSCONFDIR", "etc");
+}
+
+std::string GetSharedStateDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
+}
+
+std::string GetLocalStateDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
+}
+
+std::string GetRunStateDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_RUNSTATEDIR",
+ cmStrCat(GetLocalStateDirectory(makefile), "/run"));
+}
+
+std::string GetDataRootDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_DATAROOTDIR", "share");
+}
+
+std::string GetDataDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_DATADIR",
+ GetDataRootDirectory(makefile));
+}
+
+std::string GetInfoDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_INFODIR",
+ cmStrCat(GetDataRootDirectory(makefile), "/info"));
+}
+
+std::string GetLocaleDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_LOCALEDIR",
+ cmStrCat(GetDataRootDirectory(makefile), "/locale"));
+}
+
+std::string GetManDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_MANDIR",
+ cmStrCat(GetDataRootDirectory(makefile), "/man"));
+}
+
+std::string GetDocDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_DOCDIR",
+ cmStrCat(GetDataRootDirectory(makefile), "/doc"));
+}
+
+std::string GetLibExecDirectory(cmMakefile const* makefile)
+{
+ return GetDirectory(makefile, "CMAKE_INSTALL_LIBEXECDIR", "libexec");
+}
+
+std::string GetDirectoryForType(cmMakefile const* makefile,
+ cm::string_view type)
+{
+ if (type == "BIN"_s) {
+ return GetRuntimeDirectory(makefile);
+ }
+ if (type == "SBIN"_s) {
+ return GetSbinDirectory(makefile);
+ }
+ if (type == "SYSCONF"_s) {
+ return GetSysconfDirectory(makefile);
+ }
+ if (type == "SHAREDSTATE"_s) {
+ return GetSharedStateDirectory(makefile);
+ }
+ if (type == "LOCALSTATE"_s) {
+ return GetLocalStateDirectory(makefile);
+ }
+ if (type == "RUNSTATE"_s) {
+ return GetRunStateDirectory(makefile);
+ }
+ if (type == "LIB"_s) {
+ return GetLibraryDirectory(makefile);
+ }
+ if (type == "INCLUDE"_s) {
+ return GetIncludeDirectory(makefile);
+ }
+ if (type == "DATA"_s) {
+ return GetDataDirectory(makefile);
+ }
+ if (type == "INFO"_s) {
+ return GetInfoDirectory(makefile);
+ }
+ if (type == "LOCALE"_s) {
+ return GetLocaleDirectory(makefile);
+ }
+ if (type == "MAN"_s) {
+ return GetManDirectory(makefile);
+ }
+ if (type == "DOC"_s) {
+ return GetDocDirectory(makefile);
+ }
+ if (type == "LIBEXEC"_s) {
+ return GetLibExecDirectory(makefile);
+ }
+ return std::string{};
+}
+
+} // namespace InstallDirs
+} // namespace cm
diff --git a/Source/cmInstallDirs.h b/Source/cmInstallDirs.h
new file mode 100644
index 0000000..73cc564
--- /dev/null
+++ b/Source/cmInstallDirs.h
@@ -0,0 +1,34 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+
+#pragma once
+
+#include <string>
+
+#include <cm/string_view>
+
+class cmMakefile;
+
+namespace cm {
+
+namespace InstallDirs {
+std::string GetRuntimeDirectory(cmMakefile const*);
+std::string GetSbinDirectory(cmMakefile const*);
+std::string GetArchiveDirectory(cmMakefile const*);
+std::string GetLibraryDirectory(cmMakefile const*);
+std::string GetIncludeDirectory(cmMakefile const*);
+std::string GetSysconfDirectory(cmMakefile const*);
+std::string GetSharedStateDirectory(cmMakefile const*);
+std::string GetLocalStateDirectory(cmMakefile const*);
+std::string GetRunStateDirectory(cmMakefile const*);
+std::string GetDataRootDirectory(cmMakefile const*);
+std::string GetDataDirectory(cmMakefile const*);
+std::string GetInfoDirectory(cmMakefile const*);
+std::string GetLocaleDirectory(cmMakefile const*);
+std::string GetManDirectory(cmMakefile const*);
+std::string GetDocDirectory(cmMakefile const*);
+std::string GetLibExecDirectory(cmMakefile const*);
+
+std::string GetDirectoryForType(cmMakefile const*, cm::string_view type);
+}
+}
diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx
index 7763f43..85b8275 100644
--- a/Source/cmInstallFileSetGenerator.cxx
+++ b/Source/cmInstallFileSetGenerator.cxx
@@ -9,13 +9,14 @@
#include <vector>
#include <cm/string_view>
-#include <cmext/string_view>
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallDirs.h"
#include "cmInstallType.h"
#include "cmList.h"
#include "cmListFileCache.h"
@@ -25,16 +26,15 @@
#include "cmTarget.h"
cmInstallFileSetGenerator::cmInstallFileSetGenerator(
- std::string targetName, std::string fileSetName, cmFileSetDestinations dests,
+ std::string targetName, std::string fileSetName, std::string destination,
std::string file_permissions, std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message, bool exclude_from_all,
bool optional, cmListFileBacktrace backtrace)
- : cmInstallGenerator("", configurations, component, message,
- exclude_from_all, false, std::move(backtrace))
+ : cmInstallGenerator(std::move(destination), configurations, component,
+ message, exclude_from_all, false, std::move(backtrace))
, TargetName(std::move(targetName))
, FileSetName(std::move(fileSetName))
, FilePermissions(std::move(file_permissions))
- , FileSetDestinations(std::move(dests))
, Optional(optional)
{
this->ActionsPerConfig = true;
@@ -54,8 +54,7 @@
lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
}
- auto const& target = *this->Target->Target;
- this->FileSet = target.GetFileSet(this->FileSetName);
+ this->FileSet = this->Target->GetFileSet(this->FileSetName);
if (!this->FileSet) {
// No file set of the given name was ever provided for this target, nothing
@@ -63,15 +62,17 @@
return true;
}
+ auto const& target = *this->Target->Target;
cmList interfaceFileSetEntries{ target.GetSafeProperty(
- cmTarget::GetInterfaceFileSetsPropertyName(this->FileSet->GetType())) };
+ target.GetInterfaceFileSetsPropertyName(this->FileSet->GetType())) };
if (std::find(interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(),
this->FileSetName) != interfaceFileSetEntries.end()) {
- if (this->FileSet->GetType() == "HEADERS"_s) {
- this->Destination = this->FileSetDestinations.Headers;
- } else {
- this->Destination = this->FileSetDestinations.CXXModules;
+ if (this->FileSet->GetType() == cm::FileSetMetadata::HEADERS) {
+ if (this->Destination.empty()) {
+ this->Destination =
+ cm::InstallDirs::GetIncludeDirectory(lg->GetMakefile());
+ }
}
} else {
// File set of the given name was provided but it's private, so give up
@@ -121,19 +122,7 @@
cmInstallFileSetGenerator::CalculateFilesPerDir(
std::string const& config) const
{
- std::map<std::string, std::vector<std::string>> result;
-
cm::GenEx::Context context(this->LocalGenerator, config);
- auto dirCges = this->FileSet->CompileDirectoryEntries();
- auto dirs =
- this->FileSet->EvaluateDirectoryEntries(dirCges, context, this->Target);
-
- auto fileCges = this->FileSet->CompileFileEntries();
- for (auto const& fileCge : fileCges) {
- this->FileSet->EvaluateFileEntry(dirs, result, fileCge, context,
- this->Target);
- }
-
- return result;
+ return this->FileSet->GetFiles(context, this->Target).first;
}
diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h
index ba30414..ff56201 100644
--- a/Source/cmInstallFileSetGenerator.h
+++ b/Source/cmInstallFileSetGenerator.h
@@ -10,21 +10,15 @@
#include "cmInstallGenerator.h"
class cmGeneratorTarget;
-class cmFileSet;
+class cmGeneratorFileSet;
class cmListFileBacktrace;
class cmLocalGenerator;
-struct cmFileSetDestinations
-{
- std::string Headers;
- std::string CXXModules;
-};
-
class cmInstallFileSetGenerator : public cmInstallGenerator
{
public:
cmInstallFileSetGenerator(std::string targetName, std::string fileSetName,
- cmFileSetDestinations dests,
+ std::string destination,
std::string file_permissions,
std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message,
@@ -38,7 +32,7 @@
std::string GetDestination() const { return this->Destination; }
bool GetOptional() const { return this->Optional; }
std::string GetFileSetName() const { return this->FileSetName; }
- cmFileSet const* GetFileSet() const { return this->FileSet; };
+ cmGeneratorFileSet const* GetFileSet() const { return this->FileSet; };
cmGeneratorTarget* GetTarget() const { return this->Target; }
protected:
@@ -48,10 +42,9 @@
private:
std::string TargetName;
cmLocalGenerator* LocalGenerator;
- cmFileSet const* FileSet;
+ cmGeneratorFileSet const* FileSet;
std::string const FileSetName;
std::string const FilePermissions;
- cmFileSetDestinations FileSetDestinations;
bool const Optional;
cmGeneratorTarget* Target;
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index cc9fd8a..dd9ade7 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -217,6 +217,10 @@
std::string cmInstallGenerator::ConvertToAbsoluteDestination(
std::string const& dest)
{
+ if (dest == ".") {
+ return "${CMAKE_INSTALL_PREFIX}";
+ }
+
std::string result;
if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) {
result = "${CMAKE_INSTALL_PREFIX}/";
diff --git a/Source/cmInstallRuntimeDependencySetGenerator.cxx b/Source/cmInstallRuntimeDependencySetGenerator.cxx
index 0f9197a..ec46045 100644
--- a/Source/cmInstallRuntimeDependencySetGenerator.cxx
+++ b/Source/cmInstallRuntimeDependencySetGenerator.cxx
@@ -14,7 +14,6 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
#include "cmScriptGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmake.h"
@@ -142,7 +141,7 @@
<< GetDestDirPath(
ConvertToAbsoluteDestination(this->GetDestination(config)))
<< "/${" << this->TmpVarPrefix << "_dep_name}\" NEW_RPATH "
- << cmOutputConverter::EscapeForCMake(evaluatedRPath) << ")\n";
+ << cmScriptGenerator::Quote(evaluatedRPath) << ")\n";
}
}
}
@@ -229,8 +228,8 @@
<< "\" ${" << this->TmpVarPrefix << "_rpath_args}\n";
if (!this->NoInstallRPath) {
for (auto const& rpath : evaluatedRPaths) {
- os << indent2 << " -add_rpath "
- << cmOutputConverter::EscapeForCMake(rpath) << "\n";
+ os << indent2 << " -add_rpath " << cmScriptGenerator::Quote(rpath)
+ << '\n';
}
}
if (!this->NoInstallName) {
diff --git a/Source/cmInstallScriptHandler.cxx b/Source/cmInstallScriptHandler.cxx
index 10f795b..6a268f9 100644
--- a/Source/cmInstallScriptHandler.cxx
+++ b/Source/cmInstallScriptHandler.cxx
@@ -33,20 +33,28 @@
using InstallScript = cmInstallScriptHandler::InstallScript;
using InstallScriptRunner = cmInstallScriptHandler::InstallScriptRunner;
-cmInstallScriptHandler::cmInstallScriptHandler(std::string _binaryDir,
- std::string _component,
- std::string _config,
- std::vector<std::string>& args)
- : binaryDir(std::move(_binaryDir))
- , component(std::move(_component))
+cmInstallScriptHandler::cmInstallScriptHandler(
+ std::string _binaryDir, std::vector<std::string> _components,
+ std::string _config, std::vector<std::string>& args)
+ : components(std::move(_components))
+ , binaryDir(std::move(_binaryDir))
{
+ if (this->components.empty()) {
+ this->components.emplace_back(std::string{});
+ }
+
std::string const& file =
cmStrCat(this->binaryDir, "/CMakeFiles/InstallScripts.json");
this->parallel = false;
- auto addScript = [this, &args](std::string script,
+ auto addScript = [this, &args](std::string script, std::string component,
std::string config) -> void {
this->scripts.push_back({ script, config, args });
+ if (!component.empty()) {
+ this->scripts.back().command.insert(
+ this->scripts.back().command.end() - 1,
+ cmStrCat("-DCMAKE_INSTALL_COMPONENT=", component));
+ }
if (!config.empty()) {
this->scripts.back().command.insert(
this->scripts.back().command.end() - 1,
@@ -81,15 +89,20 @@
this->configs.push_back(_config);
}
for (auto const& script : value["InstallScripts"]) {
- for (auto const& config : configs) {
- addScript(script.asCString(), config);
+ for (auto const& component : components) {
+ for (auto const& config : configs) {
+ addScript(script.asCString(), component, config);
+ }
}
if (!this->parallel) {
break;
}
}
} else {
- addScript(cmStrCat(this->binaryDir, "/cmake_install.cmake"), _config);
+ for (auto const& component : components) {
+ addScript(cmStrCat(this->binaryDir, "/cmake_install.cmake"), component,
+ _config);
+ }
}
}
@@ -156,30 +169,31 @@
// Write install manifest
std::string install_manifest;
- if (this->component.empty()) {
- install_manifest = "install_manifest.txt";
- } else {
- cmsys::RegularExpression regEntry;
- if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") &&
- regEntry.find(this->component)) {
- install_manifest =
- cmStrCat("install_manifest_", this->component, ".txt");
+ for (auto const& component : this->components) {
+ if (component.empty()) {
+ install_manifest = "install_manifest.txt";
} else {
- cmCryptoHash md5(cmCryptoHash::AlgoMD5);
- md5.Initialize();
- install_manifest =
- cmStrCat("install_manifest_", md5.HashString(this->component), ".txt");
+ cmsys::RegularExpression regEntry;
+ if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") && regEntry.find(component)) {
+ install_manifest = cmStrCat("install_manifest_", component, ".txt");
+ } else {
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
+ md5.Initialize();
+ install_manifest =
+ cmStrCat("install_manifest_", md5.HashString(component), ".txt");
+ }
}
- }
- cmGeneratedFileStream fout(cmStrCat(this->binaryDir, '/', install_manifest));
- fout.SetCopyIfDifferent(true);
- for (auto const& dir : this->directories) {
- auto local_manifest = cmStrCat(dir, "/install_local_manifest.txt");
- if (cmSystemTools::FileExists(local_manifest)) {
- cmsys::ifstream fin(local_manifest.c_str());
- std::string line;
- while (std::getline(fin, line)) {
- fout << line << "\n";
+ cmGeneratedFileStream fout(
+ cmStrCat(this->binaryDir, '/', install_manifest));
+ fout.SetCopyIfDifferent(true);
+ for (auto const& dir : this->directories) {
+ auto local_manifest = cmStrCat(dir, "/install_local_manifest.txt");
+ if (cmSystemTools::FileExists(local_manifest)) {
+ cmsys::ifstream fin(local_manifest.c_str());
+ std::string line;
+ while (std::getline(fin, line)) {
+ fout << line << "\n";
+ }
}
}
}
diff --git a/Source/cmInstallScriptHandler.h b/Source/cmInstallScriptHandler.h
index 6f2a7d7..3fcfac0 100644
--- a/Source/cmInstallScriptHandler.h
+++ b/Source/cmInstallScriptHandler.h
@@ -21,7 +21,7 @@
{
public:
cmInstallScriptHandler() = default;
- cmInstallScriptHandler(std::string, std::string, std::string,
+ cmInstallScriptHandler(std::string, std::vector<std::string>, std::string,
std::vector<std::string>&);
bool IsParallel();
int Install(unsigned int j, cmInstrumentation& instrumentation);
@@ -51,7 +51,7 @@
std::vector<InstallScript> scripts;
std::vector<std::string> configs;
std::vector<std::string> directories;
+ std::vector<std::string> components;
std::string binaryDir;
- std::string component;
bool parallel;
};
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index fb7956e..a9be820 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -23,7 +23,6 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmObjectLocation.h"
-#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmScriptGenerator.h"
#include "cmStateTypes.h"
@@ -714,9 +713,8 @@
default: {
// Get the install RPATH from the link information and
// escape any CMake syntax in the install RPATH.
- std::string escapedNewRpath =
- cmOutputConverter::EscapeForCMake(cli->GetChrpathString());
- os << indent << " RPATH " << escapedNewRpath << ")\n";
+ os << indent << " RPATH "
+ << cmScriptGenerator::Quote(cli->GetChrpathString()) << ")\n";
break;
}
}
@@ -829,14 +827,11 @@
return;
}
- // Escape any CMake syntax in the RPATHs.
- std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath);
- std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath);
-
// Write a rule to run chrpath to set the install-tree RPATH
os << indent << "file(RPATH_CHANGE\n"
<< indent << " FILE \"" << toDestDirPath << "\"\n"
- << indent << " OLD_RPATH " << escapedOldRpath << "\n";
+ << indent << " OLD_RPATH " << cmScriptGenerator::Quote(oldRpath)
+ << "\n";
// CMP0095: ``RPATH`` entries are properly escaped in the intermediary
// CMake install script.
@@ -848,7 +843,8 @@
os << indent << " NEW_RPATH \"" << newRpath << "\"";
break;
default:
- os << indent << " NEW_RPATH " << escapedNewRpath;
+ os << indent << " NEW_RPATH "
+ << cmScriptGenerator::Quote(newRpath);
break;
}
diff --git a/Source/cmInstrumentation.cxx b/Source/cmInstrumentation.cxx
index d866c73..ea32424 100644
--- a/Source/cmInstrumentation.cxx
+++ b/Source/cmInstrumentation.cxx
@@ -365,11 +365,11 @@
if (d.Load(this->dataDir)) {
for (unsigned int i = 0; i < d.GetNumberOfFiles(); i++) {
std::string fpath = d.GetFilePath(i);
- std::string fname = d.GetFile(i);
+ std::string const& fname = d.GetFileName(i);
if (fname.rfind('.', 0) == 0 || d.FileIsDirectory(i)) {
continue;
}
- files.push_back(snippet(std::move(fname), std::move(fpath)));
+ files.push_back(snippet(fname, std::move(fpath)));
}
}
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
index 269c224..da8d6ec 100644
--- a/Source/cmJSONHelpers.h
+++ b/Source/cmJSONHelpers.h
@@ -105,6 +105,18 @@
-> bool { return func(out.*member, value, state); },
required);
}
+ template <typename U, typename M, typename F, typename C>
+ Object& Bind(cm::string_view name, M U::*member, F func, C constant,
+ bool required = true)
+ {
+ return this->BindPrivate(
+ name,
+ [func, member, constant](T& out, Json::Value const* value,
+ cmJSONState* state) -> bool {
+ return func(out.*member, value, constant, state);
+ },
+ required);
+ }
template <typename M, typename F>
Object& Bind(cm::string_view name, std::nullptr_t, F func,
bool required = true)
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 036788a..34ac595 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -15,10 +15,11 @@
#include "cmList.h"
#include "cmListFileLexer.h"
+#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmMessenger.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmake.h"
namespace {
@@ -48,12 +49,12 @@
{
public:
cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
- cmMessenger* messenger);
+ cmMakefile const* mf, std::string const& filename);
cmListFileParser(cmListFileParser const&) = delete;
cmListFileParser& operator=(cmListFileParser const&) = delete;
- bool ParseFile(char const* filename);
- bool ParseString(cm::string_view str, char const* virtual_filename);
+ bool ParseFile();
+ bool ParseString(cm::string_view str);
private:
bool Parse();
@@ -74,8 +75,8 @@
cmListFile* ListFile;
cmListFileBacktrace Backtrace;
- cmMessenger* Messenger;
- char const* FileName = nullptr;
+ cmMakefile const* Makefile;
+ std::string const& FileName;
std::unique_ptr<cmListFileLexer, void (*)(cmListFileLexer*)> Lexer;
std::string FunctionName;
long FunctionLine;
@@ -84,44 +85,52 @@
};
cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
- cmMessenger* messenger)
+ cmMakefile const* mf,
+ std::string const& filename)
: ListFile(lf)
, Backtrace(std::move(lfbt))
- , Messenger(messenger)
+ , Makefile(mf)
+ , FileName(filename)
, Lexer(cmListFileLexer_New(), cmListFileLexer_Delete)
{
}
void cmListFileParser::IssueFileOpenError(std::string const& text) const
{
- this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text,
- this->Backtrace);
+ if (this->Makefile) {
+ this->Makefile->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ text, this->Backtrace);
+ }
}
void cmListFileParser::IssueError(std::string const& text) const
{
- cmListFileContext lfc;
- lfc.FilePath = this->FileName;
- lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer.get());
- cmListFileBacktrace lfbt = this->Backtrace;
- lfbt = lfbt.Push(lfc);
- this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt);
+ if (this->Makefile) {
+ cmListFileContext lfc;
+ lfc.FilePath = this->FileName;
+ lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer.get());
+ cmListFileBacktrace lfbt = this->Backtrace;
+ lfbt = lfbt.Push(lfc);
+ this->Makefile->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ text, lfbt);
+ }
cmSystemTools::SetFatalErrorOccurred();
}
-bool cmListFileParser::ParseFile(char const* filename)
+bool cmListFileParser::ParseFile()
{
- this->FileName = filename;
+ std::string const* filename = &this->FileName;
#ifdef _WIN32
std::string expandedFileName = cmsys::Encoding::ToNarrow(
- cmSystemTools::ConvertToWindowsExtendedPath(filename));
- filename = expandedFileName.c_str();
+ cmSystemTools::ConvertToWindowsExtendedPath(*filename));
+ filename = &expandedFileName;
#endif
// Open the file.
cmListFileLexer_BOM bom;
- if (!cmListFileLexer_SetFileName(this->Lexer.get(), filename, &bom)) {
+ if (!cmListFileLexer_SetFileName(this->Lexer.get(), filename->c_str(),
+ &bom)) {
this->IssueFileOpenError("cmListFileCache: error can not open file.");
return false;
}
@@ -137,11 +146,8 @@
return this->Parse();
}
-bool cmListFileParser::ParseString(cm::string_view str,
- char const* virtual_filename)
+bool cmListFileParser::ParseString(cm::string_view str)
{
- this->FileName = virtual_filename;
-
if (!cmListFileLexer_SetString(this->Lexer.get(), str.data(),
str.length())) {
this->IssueFileOpenError("cmListFileCache: cannot allocate buffer.");
@@ -194,10 +200,12 @@
// Check if all functions are nested properly.
if (auto badNesting = this->CheckNesting()) {
- this->Messenger->IssueMessage(
- MessageType::FATAL_ERROR,
- "Flow control statements are not properly nested.",
- this->Backtrace.Push(*badNesting));
+ if (this->Makefile) {
+ this->Makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Flow control statements are not properly nested.",
+ this->Backtrace.Push(*badNesting));
+ }
cmSystemTools::SetFatalErrorOccurred();
return false;
}
@@ -286,16 +294,18 @@
}
}
- cmListFileContext lfc;
- lfc.FilePath = this->FileName;
- lfc.Line = line;
- cmListFileBacktrace lfbt = this->Backtrace;
- lfbt = lfbt.Push(lfc);
- this->Messenger->IssueMessage(
- MessageType::FATAL_ERROR,
- "Parse error. Function missing ending \")\". "
- "End of file reached.",
- lfbt);
+ if (this->Makefile) {
+ cmListFileContext lfc;
+ lfc.FilePath = this->FileName;
+ lfc.Line = line;
+ cmListFileBacktrace lfbt = this->Backtrace;
+ lfbt = lfbt.Push(lfc);
+ this->Makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Parse error. Function missing ending \")\". "
+ "End of file reached.",
+ lfbt);
+ }
return false;
}
@@ -320,10 +330,15 @@
"\n"
"Argument not separated from preceding token by whitespace.");
if (isError) {
- this->Messenger->IssueMessage(MessageType::FATAL_ERROR, msg, lfbt);
+ if (this->Makefile) {
+ this->Makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, msg, lfbt);
+ }
return false;
}
- this->Messenger->IssueMessage(MessageType::AUTHOR_WARNING, msg, lfbt);
+ if (this->Makefile) {
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg, lfbt);
+ }
return true;
}
@@ -422,7 +437,7 @@
} // anonymous namespace
-bool cmListFile::ParseFile(char const* filename, cmMessenger* messenger,
+bool cmListFile::ParseFile(std::string const& filename, cmMakefile const* mf,
cmListFileBacktrace const& lfbt)
{
if (!cmSystemTools::FileExists(filename) ||
@@ -430,28 +445,17 @@
return false;
}
- bool parseError = false;
-
- {
- cmListFileParser parser(this, lfbt, messenger);
- parseError = !parser.ParseFile(filename);
- }
-
- return !parseError;
+ cmListFileParser parser(this, lfbt, mf, filename);
+ return parser.ParseFile();
}
-bool cmListFile::ParseString(cm::string_view str, char const* virtual_filename,
- cmMessenger* messenger,
+bool cmListFile::ParseString(cm::string_view str,
+ std::string const& virtual_filename,
+ cmMakefile const* mf,
cmListFileBacktrace const& lfbt)
{
- bool parseError = false;
-
- {
- cmListFileParser parser(this, lfbt, messenger);
- parseError = !parser.ParseString(str, virtual_filename);
- }
-
- return !parseError;
+ cmListFileParser parser(this, lfbt, mf, virtual_filename);
+ return parser.ParseString(str);
}
#include "cmConstStack.tcc"
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index fd3b7b4..337fc26 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -6,6 +6,7 @@
#include <iosfwd>
#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -24,7 +25,7 @@
* cmake list files.
*/
-class cmMessenger;
+class cmMakefile;
struct cmListFileArgument
{
@@ -205,6 +206,37 @@
std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
+namespace cm {
+// Helpers for basic type retrieval
+template <typename T>
+T remove_BT(BT<T> const& bt)
+{
+ return bt.Value;
+}
+
+template <typename T>
+std::vector<T> remove_BT(std::vector<BT<T>> const& container)
+{
+ std::vector<T> result;
+ result.reserve(container.size());
+ for (auto const& entry : container) {
+ result.emplace_back(entry.Value);
+ }
+
+ return result;
+}
+template <typename T>
+std::set<T> remove_BT(std::set<BT<T>> const& container)
+{
+ std::set<T> result;
+ for (auto const& entry : container) {
+ result.emplace(entry.Value);
+ }
+
+ return result;
+}
+}
+
// Wrap type T as a value with potentially multiple backtraces. For purposes
// of ordering and equality comparison, only the original value is used. The
// backtrace is considered incidental.
@@ -238,11 +270,11 @@
struct cmListFile
{
- bool ParseFile(char const* path, cmMessenger* messenger,
+ bool ParseFile(std::string const& path, cmMakefile const* mf,
cmListFileBacktrace const& lfbt);
- bool ParseString(cm::string_view str, char const* virtual_filename,
- cmMessenger* messenger, cmListFileBacktrace const& lfbt);
+ bool ParseString(cm::string_view str, std::string const& virtual_filename,
+ cmMakefile const* mf, cmListFileBacktrace const& lfbt);
std::vector<cmListFileFunction> Functions;
};
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 2af0dc0..5856af2 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -48,6 +48,7 @@
#include "cmObjectLocation.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
+#include "cmScriptGenerator.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
@@ -231,15 +232,25 @@
{
return cm::make_unique<cmRulePlaceholderExpander>(
buildStep, this->Compilers, this->VariableMappings, this->CompilerSysroot,
- this->LinkerSysroot);
+ this->LinkerSysroot,
+ this->GetState()->UseWatcomWMake() || this->GetState()->UseBorlandMake()
+ ? cmRulePlaceholderExpander::UseShortPaths::Yes
+ : cmRulePlaceholderExpander::UseShortPaths::No);
}
cmLocalGenerator::~cmLocalGenerator() = default;
-void cmLocalGenerator::IssueMessage(MessageType t,
- std::string const& text) const
+void cmLocalGenerator::IssueMessage(MessageType type, std::string const& text,
+ cmListFileBacktrace const& bt) const
{
- this->GetCMakeInstance()->IssueMessage(t, text, this->DirectoryBacktrace);
+ this->GetMakefile()->IssueMessage(type, text, bt);
+}
+
+void cmLocalGenerator::IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& text,
+ cmListFileBacktrace const& bt) const
+{
+ this->GetMakefile()->IssueDiagnostic(category, text, bt);
}
void cmLocalGenerator::ComputeObjectMaxPath()
@@ -389,8 +400,7 @@
// TODO: Use add_subdirectory instead?
std::string outP = i.GetDirectory().GetCurrentBinary();
outP = this->MaybeRelativeToCurBinDir(outP);
- outP = cmOutputConverter::EscapeForCMake(outP);
- fout << "subdirs(" << outP << ")\n";
+ fout << "subdirs(" << cmScriptGenerator::Quote(outP) << ")\n";
}
// Add directory labels property
@@ -401,13 +411,13 @@
if (labels || directoryLabels) {
fout << "set_directory_properties(PROPERTIES LABELS ";
if (labels) {
- fout << cmOutputConverter::EscapeForCMake(*labels);
+ fout << cmScriptGenerator::Quote(*labels);
}
if (labels && directoryLabels) {
fout << ";";
}
if (directoryLabels) {
- fout << cmOutputConverter::EscapeForCMake(*directoryLabels);
+ fout << cmScriptGenerator::Quote(*directoryLabels);
}
fout << ")\n";
}
@@ -2130,6 +2140,8 @@
}
} else if (lang == "HIP") {
target->AddHIPArchitectureFlags(compileOrLink, config, flags);
+ } else if (lang == "Rust") {
+ target->AddRustTargetFlags(flags);
}
// Add VFS Overlay for Clang compilers
@@ -2307,7 +2319,8 @@
bool cmLocalGenerator::GetRealDependency(std::string const& inName,
std::string const& config,
- std::string& dep)
+ std::string& dep,
+ cmPolicies::PolicyStatus cmp0212)
{
// Older CMake code may specify the dependency using the target
// output file rather than the target name. Such code would have
@@ -2321,12 +2334,21 @@
if (name.empty()) {
return false;
}
- if (cmHasSuffix(name, ".exe"_s)) {
- name = cmSystemTools::GetFilenameWithoutLastExtension(name);
- }
// Look for a CMake target with the given name.
- if (cmGeneratorTarget* target = this->FindGeneratorTargetToUse(name)) {
+ cmGeneratorTarget* target = this->FindGeneratorTargetToUse(name);
+ if (!target && cmHasSuffix(name, ".exe"_s) && cmp0212 != cmPolicies::NEW) {
+ // If it doesn't exist, try to strip the `.exe` suffix per CMP0212.
+ std::string strippedName =
+ cmSystemTools::GetFilenameWithoutLastExtension(name);
+ if (cmGeneratorTarget* strippedTarget =
+ this->FindGeneratorTargetToUse(strippedName)) {
+ name = strippedName;
+ target = strippedTarget;
+ }
+ }
+
+ if (target) {
// make sure it is not just a coincidence that the target name
// found is part of the inName
if (cmSystemTools::FileIsFullPath(inName)) {
@@ -2685,8 +2707,11 @@
cmStrCat(headerDir, '/', ispcSource, *ispcHeaderSuffixProp);
target->AddISPCGeneratedHeader(headerPath, config);
if (extra_objects) {
- std::vector<std::string> objs = detail::ComputeISPCExtraObjects(
- objectName, rootObjectDir, ispcArchSuffixes);
+ std::vector<std::pair<cmSourceFile const*, std::string>> objs;
+ for (auto& obj : detail::ComputeISPCExtraObjects(
+ objectName, rootObjectDir, ispcArchSuffixes)) {
+ objs.push_back({ sf, std::move(obj) });
+ }
target->AddISPCGeneratedObject(std::move(objs), config);
}
}
@@ -3590,8 +3615,12 @@
}
char const* PICValue = target->GetLinkPIEProperty(config);
- if (!PICValue) {
- // POSITION_INDEPENDENT_CODE is not set
+ if (!PICValue && lang != "Rust") {
+ // POSITION_INDEPENDENT_CODE is not set, note that for Rust we do not
+ // return as the compiler tends to enable PIE all the time, which is the
+ // opposite of what C & C++ compilers do. So instead of letting the rust
+ // compiler decide on its own whether PIE should be enabled, we explicit
+ // set it.
return;
}
@@ -3885,6 +3914,17 @@
}
}
+void cmLocalGenerator::AppendDefines(
+ std::set<std::string>& defines,
+ std::vector<BT<std::string>> const& defines_vec) const
+{
+ std::set<BT<std::string>> tmp;
+ this->AppendDefines(tmp, defines_vec);
+ for (BT<std::string> const& i : tmp) {
+ defines.emplace(i.Value);
+ }
+}
+
void cmLocalGenerator::AppendDefines(std::set<BT<std::string>>& defines,
std::string const& defines_list) const
{
@@ -4668,6 +4708,20 @@
*hasSourceExtension = keptSourceExtension;
}
+ if (source.GetLanguage() == "Rust") {
+ cmValue const rustEmit = source.GetRustEmitProperty();
+ // Rust requires any rlib to start with lib prefix on all platforms to
+ // allow linking to them as crate. So we enforce having lib prefix for rust
+ // "object" files.
+ if (rustEmit == "link") {
+ cmCMakePath objectPath(objectName);
+ std::string const objectFileName =
+ "lib" + objectPath.GetFileName().String();
+ objectPath.ReplaceFileName(objectFileName);
+ objectName = objectPath.String();
+ }
+ }
+
// Convert to a safe name.
return this->CreateSafeUniqueObjectFileName(objectName, dir_max);
}
@@ -5184,9 +5238,15 @@
// transform targets into the suffixes
auto pos = ispcTarget.find('-');
auto target_suffix = ispcTarget.substr(0, pos);
+ // ISPC uses underscores in output file suffixes where the target name
+ // has dots (e.g. "avx10.2dmr" produces files with "_avx10_2dmr" suffix)
+ std::replace(target_suffix.begin(), target_suffix.end(), '.', '_');
if (target_suffix ==
"avx1") { // when targeting avx1 ISPC uses the 'avx' output string
target_suffix = "avx";
+ } else if (target_suffix == "sse4_1" || target_suffix == "sse4_2") {
+ // when targeting sse4.1 or sse4.2 ISPC uses the 'sse4' output string
+ target_suffix = "sse4";
}
ispcTarget = target_suffix;
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 50e710f..77f1e30 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -17,6 +17,7 @@
#include <cm/optional>
#include "cmCustomCommandTypes.h"
+#include "cmDiagnostics.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmListFileCache.h"
@@ -265,6 +266,8 @@
*/
void AppendDefines(std::set<std::string>& defines,
std::string const& defines_list) const;
+ void AppendDefines(std::set<std::string>& defines,
+ std::vector<BT<std::string>> const& defines_vec) const;
void AppendDefines(std::set<BT<std::string>>& defines,
std::string const& defines_list) const;
void AppendDefines(std::set<BT<std::string>>& defines,
@@ -309,7 +312,7 @@
* used for dependencies of custom commands.
*/
bool GetRealDependency(std::string const& name, std::string const& config,
- std::string& dep);
+ std::string& dep, cmPolicies::PolicyStatus cmp0212);
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {}
@@ -569,7 +572,19 @@
bool IsNinjaMulti() const;
bool IsWindowsVSIDE() const;
- void IssueMessage(MessageType t, std::string const& text) const;
+ void IssueMessage(MessageType type, std::string const& text) const
+ {
+ this->IssueMessage(type, text, this->DirectoryBacktrace);
+ }
+ void IssueMessage(MessageType type, std::string const& text,
+ cmListFileBacktrace const& bt) const;
+ void IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& text) const
+ {
+ this->IssueDiagnostic(category, text, this->DirectoryBacktrace);
+ }
+ void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text,
+ cmListFileBacktrace const& bt) const;
void CreateEvaluationFileOutputs();
void CreateEvaluationFileOutputs(std::string const& config);
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index b6cc3a6..dc319af 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -414,7 +414,8 @@
{
for (std::string const& i : ccg.GetDepends()) {
std::string dep;
- if (this->GetRealDependency(i, config, dep)) {
+ if (this->GetRealDependency(i, config, dep,
+ ccg.GetCC().GetCMP0212Status())) {
ninjaDeps.push_back(
this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep));
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index d9b2c0f..dca015b 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -37,6 +37,7 @@
#include "cmOutputConverter.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
+#include "cmScriptGenerator.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
@@ -956,7 +957,8 @@
for (std::string const& d : ccg.GetDepends()) {
// Lookup the real name of the dependency in case it is a CMake target.
std::string dep;
- if (this->GetRealDependency(d, this->GetConfigName(), dep)) {
+ if (this->GetRealDependency(d, this->GetConfigName(), dep,
+ ccg.GetCC().GetCMP0212Status())) {
depends.push_back(std::move(dep));
}
}
@@ -1154,7 +1156,7 @@
fout << "file(REMOVE_RECURSE\n";
for (std::string const& file : files) {
std::string fc = this->MaybeRelativeToCurBinDir(file);
- fout << " " << cmOutputConverter::EscapeForCMake(fc) << '\n';
+ fout << " " << cmScriptGenerator::Quote(fc) << '\n';
}
fout << ")\n";
}
@@ -1215,7 +1217,7 @@
for (std::string const& cfl : cleanFiles) {
std::string fc = rootLG->MaybeRelativeToCurBinDir(
cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
- fout << " " << cmOutputConverter::EscapeForCMake(fc) << '\n';
+ fout << " " << cmScriptGenerator::Quote(fc) << '\n';
}
fout << ")\n";
}
@@ -2027,8 +2029,7 @@
"set(CMAKE_TARGET_DEFINITIONS_"
<< lang << '\n';
for (std::string const& define : defines) {
- cmakefileStream << " " << cmOutputConverter::EscapeForCMake(define)
- << '\n';
+ cmakefileStream << " " << cmScriptGenerator::Quote(define) << '\n';
}
cmakefileStream << " )\n";
}
@@ -2068,8 +2069,7 @@
if (!transformRules.empty()) {
cmakefileStream << "\nset(CMAKE_INCLUDE_TRANSFORMS\n";
for (std::string const& tr : transformRules) {
- cmakefileStream << " " << cmOutputConverter::EscapeForCMake(tr)
- << '\n';
+ cmakefileStream << " " << cmScriptGenerator::Quote(tr) << '\n';
}
cmakefileStream << " )\n";
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 567ce3b..6de9c50 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -24,6 +24,8 @@
#include "cmCustomCommandLines.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -1496,6 +1498,9 @@
}
cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gt, lang);
+ // lookup for the associated file set, if any.
+ auto const* fileSet =
+ gt->GetGeneratorFileSets()->GetFileSetForSource(config, &sf);
bool needfc = false;
if (!objectName.empty()) {
@@ -1514,6 +1519,15 @@
genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
needfc = true;
}
+ // Add flags from file set properties.
+ if (fileSet) {
+ auto options = fileSet->BelongsTo(gt)
+ ? fileSet->GetCompileOptions(config, lang)
+ : fileSet->GetInterfaceCompileOptions(config, lang);
+ if (!options.empty()) {
+ lg->AppendCompileOptions(fc.CompileFlags, cm::remove_BT(options));
+ }
+ }
// Add precompile headers compile options.
std::string const pchSource = gt->GetPchSource(config, lang);
if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
@@ -1570,10 +1584,36 @@
genexInterpreter.Evaluate(*ccdefs, COMPILE_DEFINITIONS);
needfc = true;
}
+ // Add file set preprocessor definitions
+ if (fileSet) {
+ auto defines = fileSet->BelongsTo(gt)
+ ? fileSet->GetCompileDefinitions(config, lang)
+ : fileSet->GetInterfaceCompileDefinitions(config, lang);
+ if (!defines.empty()) {
+ if (!fc.CompileDefs.empty()) {
+ fc.CompileDefs += ';';
+ }
+ fc.CompileDefs += cmList::to_string(defines);
+ needfc = true;
+ }
+ }
+ // Add file set include directories definitions
+ if (fileSet) {
+ auto includes = fileSet->BelongsTo(gt)
+ ? fileSet->GetIncludeDirectories(config, lang)
+ : fileSet->GetInterfaceIncludeDirectories(config, lang);
+ if (!includes.empty()) {
+ fc.IncludeDirs = cmList::to_string(includes);
+ needfc = true;
+ }
+ }
std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (cmValue cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
- fc.IncludeDirs = genexInterpreter.Evaluate(*cincs, INCLUDE_DIRECTORIES);
+ if (!fc.IncludeDirs.empty()) {
+ fc.IncludeDirs += ';';
+ }
+ fc.IncludeDirs += genexInterpreter.Evaluate(*cincs, INCLUDE_DIRECTORIES);
needfc = true;
}
@@ -1868,7 +1908,8 @@
for (std::string const& d : ccg.GetDepends()) {
// Get the real name of the dependency in case it is a CMake target.
std::string dep;
- if (this->GetRealDependency(d, config, dep)) {
+ if (this->GetRealDependency(d, config, dep,
+ command.GetCMP0212Status())) {
fout << this->ConvertToXMLOutputPath(dep) << ";";
}
}
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index c1506a4..f193bce 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -10,6 +10,7 @@
#include <cmext/algorithm>
#include <cmext/string_view>
+#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
#include "cmList.h"
@@ -37,6 +38,7 @@
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
cmPolicies::PolicyMap Policies;
+ cmDiagnostics::DiagnosticMap Diagnostics;
std::string FilePath;
};
@@ -61,7 +63,7 @@
}
cmMakefile::MacroPushPop macroScope(&makefile, this->FilePath,
- this->Policies);
+ this->Policies, this->Diagnostics);
// set the value of argc
std::string argcDef = std::to_string(expandedArgs.size());
@@ -175,6 +177,7 @@
f.Functions = std::move(functions);
f.FilePath = this->GetStartingContext().FilePath;
mf.RecordPolicies(f.Policies);
+ mf.RecordDiagnostics(f.Diagnostics);
return mf.GetState()->AddScriptedCommand(
this->Args[0],
BT<cmState::Command>(std::move(f),
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 16ed8d6..ae1cba4 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -174,8 +174,9 @@
this->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
this->StateSnapshot);
- // Enter a policy level for this directory.
+ // Enter a policy and diagnostic level for this directory.
this->PushPolicy();
+ this->PushDiagnostic();
// push empty loop block
this->PushLoopBlockBarrier();
@@ -212,7 +213,8 @@
return std::string(buf);
}
-void cmMakefile::IssueMessage(MessageType t, std::string const& text) const
+void cmMakefile::IssueMessage(MessageType t, std::string const& text,
+ cmListFileBacktrace const& bt) const
{
if (!this->ExecutionStatusStack.empty()) {
if ((t == MessageType::FATAL_ERROR) ||
@@ -220,7 +222,21 @@
this->ExecutionStatusStack.back()->SetNestedError();
}
}
- this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace);
+ this->GetCMakeInstance()->IssueMessage(t, text, bt);
+}
+
+void cmMakefile::IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& text,
+ cmListFileBacktrace const& bt) const
+{
+ if (!this->ExecutionStatusStack.empty()) {
+ cmDiagnosticAction const action = this->GetDiagnosticAction(category);
+ if (action >= cmDiagnosticAction::SendError) {
+ this->ExecutionStatusStack.back()->SetNestedError();
+ }
+ }
+ this->GetCMakeInstance()->IssueDiagnostic(category, text,
+ this->GetStateSnapshot(), bt);
}
Message::LogLevel cmMakefile::GetCurrentLogLevel() const
@@ -619,7 +635,8 @@
{
public:
IncludeScope(cmMakefile* mf, std::string const& filenametoread,
- bool noPolicyScope);
+ cm::PolicyScope policyScope,
+ cm::DiagnosticScope diagnosticScope);
~IncludeScope();
void Quiet() { this->ReportError = false; }
@@ -627,15 +644,18 @@
IncludeScope& operator=(IncludeScope const&) = delete;
private:
- bool NoPolicyScope;
+ cm::PolicyScope PolicyScope;
+ cm::DiagnosticScope DiagnosticScope;
bool ReportError = true;
};
cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
std::string const& filenametoread,
- bool noPolicyScope)
+ cm::PolicyScope policyScope,
+ cm::DiagnosticScope diagnosticScope)
: FileScopeBase(mf)
- , NoPolicyScope(noPolicyScope)
+ , PolicyScope(policyScope)
+ , DiagnosticScope(diagnosticScope)
{
this->Makefile->Backtrace = this->Makefile->Backtrace.Push(
cmListFileContext::FromListFilePath(filenametoread));
@@ -645,16 +665,23 @@
this->Makefile->StateSnapshot =
this->Makefile->GetState()->CreateIncludeFileSnapshot(
this->Makefile->StateSnapshot, filenametoread);
- if (!this->NoPolicyScope) {
+ if (this->PolicyScope == cm::PolicyScope::Local) {
this->Makefile->PushPolicy();
}
+ if (this->DiagnosticScope == cm::DiagnosticScope::Local) {
+ this->Makefile->PushDiagnostic();
+ }
this->PushListFileVars(filenametoread);
}
cmMakefile::IncludeScope::~IncludeScope()
{
this->PopListFileVars();
- if (!this->NoPolicyScope) {
+ if (this->DiagnosticScope == cm::DiagnosticScope::Local) {
+ // Pop the scope we pushed for the script.
+ this->Makefile->PopDiagnostic();
+ }
+ if (this->PolicyScope == cm::PolicyScope::Local) {
// Pop the scope we pushed for the script.
this->Makefile->PopPolicy();
}
@@ -666,12 +693,13 @@
}
bool cmMakefile::ReadDependentFile(std::string const& filename,
- bool noPolicyScope)
+ cm::PolicyScope policyScope,
+ cm::DiagnosticScope diagnosticScope)
{
std::string filenametoread = cmSystemTools::CollapseFullPath(
filename, this->GetCurrentSourceDirectory());
- IncludeScope incScope(this, filenametoread, noPolicyScope);
+ IncludeScope incScope(this, filenametoread, policyScope, diagnosticScope);
#ifdef CMake_ENABLE_DEBUGGER
if (this->GetCMakeInstance()->GetDebugAdapter()) {
@@ -681,8 +709,7 @@
#endif
cmListFile listFile;
- if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
- this->Backtrace)) {
+ if (!listFile.ParseFile(filenametoread, this, this->Backtrace)) {
#ifdef CMake_ENABLE_DEBUGGER
if (this->GetCMakeInstance()->GetDebugAdapter()) {
this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
@@ -804,8 +831,7 @@
#endif
cmListFile listFile;
- if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
- this->Backtrace)) {
+ if (!listFile.ParseFile(filenametoread, this, this->Backtrace)) {
#ifdef CMake_ENABLE_DEBUGGER
if (this->GetCMakeInstance()->GetDebugAdapter()) {
this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
@@ -839,8 +865,7 @@
ListFileScope scope(this, filenametoread);
cmListFile listFile;
- if (!listFile.ParseString(content, virtualFileName.c_str(),
- this->GetMessenger(), this->Backtrace)) {
+ if (!listFile.ParseString(content, virtualFileName, this, this->Backtrace)) {
return false;
}
@@ -1441,7 +1466,8 @@
}
void cmMakefile::PushFunctionScope(std::string const& fileName,
- cmPolicies::PolicyMap const& pm)
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm)
{
this->StateSnapshot = this->GetState()->CreateFunctionCallSnapshot(
this->StateSnapshot, fileName);
@@ -1456,10 +1482,12 @@
this->PushFunctionBlockerBarrier();
this->PushPolicy(true, pm);
+ this->PushDiagnostic(true, dm);
}
void cmMakefile::PopFunctionScope(bool reportError)
{
+ this->PopDiagnostic();
this->PopPolicy();
this->PopSnapshot(reportError);
@@ -1474,7 +1502,8 @@
}
void cmMakefile::PushMacroScope(std::string const& fileName,
- cmPolicies::PolicyMap const& pm)
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm)
{
this->StateSnapshot =
this->GetState()->CreateMacroCallSnapshot(this->StateSnapshot, fileName);
@@ -1483,10 +1512,12 @@
this->PushFunctionBlockerBarrier();
this->PushPolicy(true, pm);
+ this->PushDiagnostic(true, dm);
}
void cmMakefile::PopMacroScope(bool reportError)
{
+ this->PopDiagnostic();
this->PopPolicy();
this->PopSnapshot(reportError);
@@ -1593,8 +1624,7 @@
#endif
cmListFile listFile;
- if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(),
- this->Backtrace)) {
+ if (!listFile.ParseFile(currentStart, this, this->Backtrace)) {
#ifdef CMake_ENABLE_DEBUGGER
if (this->GetCMakeInstance()->GetDebugAdapter()) {
this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
@@ -1935,7 +1965,9 @@
// check to see if we need to print a warning
// if strict mode is on and the variable has
// not been "cleared"/initialized with a set(foo ) call
- if (this->GetCMakeInstance()->GetWarnUninitialized() &&
+ cmDiagnosticAction const action =
+ this->GetDiagnosticAction(cmDiagnostics::CMD_UNINITIALIZED);
+ if (action != cmDiagnostics::Ignore &&
!this->VariableInitialized(variable)) {
if (this->CheckSystemVars ||
(sourceFilename && this->IsProjectFile(sourceFilename))) {
@@ -3287,7 +3319,7 @@
if (cmakeArgs) {
// FIXME: Workaround to ignore unused CLI variables in try-compile.
//
- // Ideally we should use SetArgs for options like --no-warn-unused-cli.
+ // Ideally we should use SetArgs for options like -Wno-unused-cli.
// However, there is a subtle problem when certain arguments are passed to
// a macro wrapping around try_compile or try_run that does not escape
// semicolons in its parameters but just passes ${ARGV} or ${ARGN}. In
@@ -3306,8 +3338,9 @@
// the value VAR=a is sufficient for the try_compile or try_run to get the
// correct result. Calling SetArgs here would break such projects that
// previously built. Instead we work around the issue by never reporting
- // unused arguments and ignoring options such as --no-warn-unused-cli.
- cm.SetWarnUnusedCli(false);
+ // unused arguments and ignoring options such as -Wno-unused-cli.
+ cm.GetCurrentSnapshot().SetDiagnostic(cmDiagnostics::CMD_UNUSED_CLI,
+ cmDiagnostics::Ignore, true);
// cm.SetArgs(*cmakeArgs, true);
cm.SetCacheArgs(*cmakeArgs);
@@ -3315,12 +3348,12 @@
// to save time we pass the EnableLanguage info directly
cm.GetGlobalGenerator()->EnableLanguagesFromGenerator(
this->GetGlobalGenerator(), this);
- if (this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
- cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", "",
- cmStateEnums::INTERNAL);
- } else {
- cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE", "",
- cmStateEnums::INTERNAL);
+ for (unsigned dc = 1; dc < cmDiagnostics::CategoryCount; ++dc) {
+ auto const category = static_cast<cmDiagnosticCategory>(dc);
+ if (this->GetDiagnosticAction(category) == cmDiagnostics::Ignore) {
+ cm.GetCurrentSnapshot().SetDiagnostic(category, cmDiagnostics::Ignore,
+ false);
+ }
}
if (cm.Configure() != 0) {
this->IssueMessage(MessageType::FATAL_ERROR,
@@ -4094,14 +4127,15 @@
}
// Deprecate old policies.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0151 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0155 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
id == cmPolicies::CMP0083 || id == cmPolicies::CMP0091 ||
id == cmPolicies::CMP0104 || id == cmPolicies::CMP0123 ||
id == cmPolicies::CMP0126 || id == cmPolicies::CMP0128 ||
- id == cmPolicies::CMP0136 || id == cmPolicies::CMP0141)) &&
+ id == cmPolicies::CMP0136 || id == cmPolicies::CMP0141 ||
+ id == cmPolicies::CMP0155)) &&
(!this->IsSet("CMAKE_WARN_DEPRECATED") ||
this->IsOn("CMAKE_WARN_DEPRECATED"))) {
this->IssueMessage(MessageType::DEPRECATION_WARNING,
@@ -4144,18 +4178,80 @@
}
}
+cmDiagnosticAction cmMakefile::GetDiagnosticAction(
+ cmDiagnosticCategory category) const
+{
+ return this->StateSnapshot.GetDiagnostic(category);
+}
+
+bool cmMakefile::SetDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive)
+{
+ this->StateSnapshot.SetDiagnostic(category, action, recursive);
+ return true;
+}
+
+bool cmMakefile::PromoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive)
+{
+ this->StateSnapshot.PromoteDiagnostic(category, action, recursive);
+ return true;
+}
+
+bool cmMakefile::DemoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive)
+{
+ this->StateSnapshot.DemoteDiagnostic(category, action, recursive);
+ return true;
+}
+
+cmMakefile::DiagnosticPushPop::DiagnosticPushPop(cmMakefile* m)
+ : Makefile(m)
+{
+ this->Makefile->PushDiagnostic();
+}
+
+cmMakefile::DiagnosticPushPop::~DiagnosticPushPop()
+{
+ this->Makefile->PopDiagnostic();
+}
+
+void cmMakefile::PushDiagnostic(bool weak, cmDiagnostics::DiagnosticMap dm)
+{
+ this->StateSnapshot.PushDiagnostic(dm, weak);
+}
+
+void cmMakefile::PopDiagnostic()
+{
+ if (!this->StateSnapshot.PopDiagnostic()) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ "cmake_diagnostic POP without matching PUSH");
+ }
+}
+
void cmMakefile::PopSnapshot(bool reportError)
{
- // cmStateSnapshot manages nested policy scopes within it.
+ // cmStateSnapshot manages nested policy/diagnostic scopes within it.
// Since the scope corresponding to the snapshot is closing,
- // reject any still-open nested policy scopes with an error.
- while (this->StateSnapshot.CanPopPolicyScope()) {
- if (reportError) {
- this->IssueMessage(MessageType::FATAL_ERROR,
- "cmake_policy PUSH without matching POP");
- reportError = false;
+ // reject any still-open nested policy/diagnostic scopes with an error.
+ for (;;) {
+ if (this->StateSnapshot.CanPopPolicyScope()) {
+ if (reportError) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ "cmake_policy PUSH without matching POP");
+ reportError = false;
+ }
+ this->PopPolicy();
+ } else if (this->StateSnapshot.CanPopDiagnosticScope()) {
+ if (reportError) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ "cmake_diagnostic PUSH without matching POP");
+ reportError = false;
+ }
+ this->PopDiagnostic();
+ } else {
+ break;
}
- this->PopPolicy();
}
this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
@@ -4207,12 +4303,22 @@
}
}
+void cmMakefile::RecordDiagnostics(cmDiagnostics::DiagnosticMap& dm) const
+{
+ /* Record the setting of every diagnostic category. */
+ for (unsigned n = 0; n < cmDiagnostics::CategoryCount; ++n) {
+ cmDiagnosticCategory const dc = static_cast<cmDiagnosticCategory>(n);
+ dm[dc] = this->GetDiagnosticAction(dc);
+ }
+}
+
cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf,
std::string const& fileName,
- cmPolicies::PolicyMap const& pm)
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm)
: Makefile(mf)
{
- this->Makefile->PushFunctionScope(fileName, pm);
+ this->Makefile->PushFunctionScope(fileName, pm, dm);
}
cmMakefile::FunctionPushPop::~FunctionPushPop()
@@ -4222,10 +4328,11 @@
cmMakefile::MacroPushPop::MacroPushPop(cmMakefile* mf,
std::string const& fileName,
- cmPolicies::PolicyMap const& pm)
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm)
: Makefile(mf)
{
- this->Makefile->PushMacroScope(fileName, pm);
+ this->Makefile->PushMacroScope(fileName, pm, dm);
}
cmMakefile::MacroPushPop::~MacroPushPop()
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index f2f06d1..41fff12 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -25,6 +25,7 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
+#include "cmDiagnostics.h"
#include "cmFindPackageStack.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
@@ -64,6 +65,20 @@
class cmVariableWatch;
class cmake;
+namespace cm {
+enum class PolicyScope : bool
+{
+ None,
+ Local,
+};
+
+enum class DiagnosticScope : bool
+{
+ None,
+ Local,
+};
+}
+
/** A type-safe wrapper for a string representing a directory id. */
class cmDirectoryId
{
@@ -108,8 +123,10 @@
bool ReadListFileAsString(std::string const& content,
std::string const& virtualFileName);
- bool ReadDependentFile(std::string const& filename,
- bool noPolicyScope = true);
+ bool ReadDependentFile(
+ std::string const& filename,
+ cm::PolicyScope policyScope = cm::PolicyScope::None,
+ cm::DiagnosticScope DiagnosticScope = cm::DiagnosticScope::None);
/**
* Add a function blocker to this makefile
@@ -391,6 +408,20 @@
void RecordPolicies(cmPolicies::PolicyMap& pm) const;
//@}
+ //@{
+ /**
+ * Set, Push, Pop diagnostics for CMake.
+ */
+ bool SetDiagnostic(cmDiagnosticCategory category, cmDiagnosticAction action,
+ bool recursive = false);
+ bool PromoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive = false);
+ bool DemoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive = false);
+ cmDiagnosticAction GetDiagnosticAction(cmDiagnosticCategory category) const;
+ void RecordDiagnostics(cmDiagnostics::DiagnosticMap& dm) const;
+ //@}
+
/** Update CMAKE_PARENT_LIST_FILE based on CMP0198 policy status. */
void UpdateParentListFileVariable();
@@ -409,6 +440,21 @@
};
friend class PolicyPushPop;
+ /** Helper class to push and pop diagnostics automatically. */
+ class DiagnosticPushPop
+ {
+ public:
+ DiagnosticPushPop(cmMakefile* m);
+ ~DiagnosticPushPop();
+
+ DiagnosticPushPop(DiagnosticPushPop const&) = delete;
+ DiagnosticPushPop& operator=(DiagnosticPushPop const&) = delete;
+
+ private:
+ cmMakefile* Makefile;
+ };
+ friend class DiagnosticPushPop;
+
/** Helper class to push and pop variables scopes automatically. */
class VariablePushPop
{
@@ -881,7 +927,8 @@
{
public:
FunctionPushPop(cmMakefile* mf, std::string const& fileName,
- cmPolicies::PolicyMap const& pm);
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm);
~FunctionPushPop();
FunctionPushPop(FunctionPushPop const&) = delete;
@@ -898,7 +945,8 @@
{
public:
MacroPushPop(cmMakefile* mf, std::string const& fileName,
- cmPolicies::PolicyMap const& pm);
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm);
~MacroPushPop();
MacroPushPop(MacroPushPop const&) = delete;
@@ -912,10 +960,12 @@
};
void PushFunctionScope(std::string const& fileName,
- cmPolicies::PolicyMap const& pm);
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm);
void PopFunctionScope(bool reportError);
void PushMacroScope(std::string const& fileName,
- cmPolicies::PolicyMap const& pm);
+ cmPolicies::PolicyMap const& pm,
+ cmDiagnostics::DiagnosticMap dm);
void PopMacroScope(bool reportError);
void PushScope();
void PopScope();
@@ -987,7 +1037,20 @@
cmMakefile* Makefile;
};
- void IssueMessage(MessageType t, std::string const& text) const;
+ void IssueMessage(MessageType t, std::string const& text) const
+ {
+ this->IssueMessage(t, text, this->Backtrace);
+ }
+ void IssueMessage(MessageType t, std::string const& text,
+ cmListFileBacktrace const& bt) const;
+
+ void IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& text) const
+ {
+ this->IssueDiagnostic(category, text, this->Backtrace);
+ }
+ void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text,
+ cmListFileBacktrace const& bt) const;
Message::LogLevel GetCurrentLogLevel() const;
/** Set whether or not to report a CMP0000 violation. */
@@ -1219,12 +1282,19 @@
TargetMap ImportedTargets;
// Internal policy stack management.
- void PushPolicy(bool weak = false,
- cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap());
+ void PushPolicy(bool weak = false, cmPolicies::PolicyMap const& pm = {});
void PopPolicy();
- void PopSnapshot(bool reportError = true);
friend bool cmCMakePolicyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status);
+
+ // Internal diagnostic stack management.
+ void PushDiagnostic(bool weak = false, cmDiagnostics::DiagnosticMap dm = {});
+ void PopDiagnostic();
+ friend bool cmCMakeDiagnosticCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+ void PopSnapshot(bool reportError = true);
+
class IncludeScope;
friend class IncludeScope;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 86c1138..77b1550 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -24,15 +24,18 @@
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmList.h"
+#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
@@ -45,6 +48,7 @@
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
+#include "cmScriptGenerator.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
@@ -53,7 +57,6 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"
@@ -238,9 +241,9 @@
// Look for ISPC extra object files generated by this target
auto const ispcAdditionalObjs =
this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
- for (std::string const& ispcObj : ispcAdditionalObjs) {
+ for (auto const& ispcObj : ispcAdditionalObjs) {
this->CleanFiles.insert(
- this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj));
+ this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj.second));
}
// add custom commands to the clean rules?
@@ -344,38 +347,6 @@
}
}
- std::map<std::string, std::string> file_set_map;
-
- auto const* tgt = this->GeneratorTarget->Target;
- for (auto const& name : tgt->GetAllFileSetNames()) {
- auto const* file_set = tgt->GetFileSet(name);
- if (!file_set) {
- this->Makefile->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("Target \"", tgt->GetName(),
- "\" is tracked to have file set \"", name,
- "\", but it was not found."));
- continue;
- }
-
- auto fileEntries = file_set->CompileFileEntries();
- auto directoryEntries = file_set->CompileDirectoryEntries();
- auto directories = file_set->EvaluateDirectoryEntries(
- directoryEntries, context, this->GeneratorTarget);
-
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- file_set->EvaluateFileEntry(directories, files, entry, context,
- this->GeneratorTarget);
- }
-
- for (auto const& it : files) {
- for (auto const& filename : it.second) {
- file_set_map[filename] = file_set->GetType();
- }
- }
- }
-
std::vector<cmSourceFile const*> objectSources;
this->GeneratorTarget->GetObjectSources(objectSources,
this->GetConfigName());
@@ -390,20 +361,17 @@
}
for (cmSourceFile const* sf : objectSources) {
- auto const& path = sf->GetFullPath();
- auto const it = file_set_map.find(path);
- if (it != file_set_map.end()) {
- auto const& file_set_type = it->second;
- if (file_set_type == "CXX_MODULES"_s) {
- if (sf->GetLanguage() != "CXX"_s) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(
- "Target \"", tgt->GetName(), "\" contains the source\n ", path,
- "\nin a file set of type \"", file_set_type,
- R"(" but the source is not classified as a "CXX" source.)"));
- }
- }
+ cmGeneratorFileSet const* fileSet =
+ this->GeneratorTarget->GetFileSetForSource(this->GetConfigName(), sf);
+ if (fileSet && fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES &&
+ sf->GetLanguage() != "CXX"_s) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Target \"", this->GeneratorTarget->GetName(),
+ "\" contains the source\n ", sf->GetFullPath(),
+ "\nin a file set of type \"",
+ cm::FileSetMetadata::CXX_MODULES,
+ R"(" but the source is not classified as a "CXX" source.)"));
}
}
}
@@ -783,6 +751,11 @@
ispcHeaderRelative, cmOutputConverter::SHELL);
}
+ // lookup for the associated file set, if any.
+ auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ config, &source);
+
// Add flags from source file properties.
std::string const COMPILE_FLAGS("COMPILE_FLAGS");
if (cmValue cflags = source.GetProperty(COMPILE_FLAGS)) {
@@ -804,6 +777,22 @@
<< "\n";
}
+ // Add flags from file set properties.
+ if (fileSet) {
+ auto options = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileOptions(config, lang)
+ : fileSet->GetInterfaceCompileOptions(config, lang);
+ if (!options.empty()) {
+ this->LocalGenerator->AppendCompileOptions(flags,
+ cm::remove_BT(options));
+ *this->FlagFileStream << "# Custom options (File Set '"
+ << fileSet->GetName() << "'): " << relativeObj
+ << "_OPTIONS = " << cmList::to_string(options)
+ << "\n"
+ << "\n";
+ }
+ }
+
// Add precompile headers compile options.
if (!pchSources.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
@@ -825,9 +814,25 @@
<< "\n";
}
- // Add include directories from source file properties.
+ // Add include directories from file set properties.
std::vector<std::string> includes;
+ if (fileSet) {
+ auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetIncludeDirectories(config, lang)
+ : fileSet->GetInterfaceIncludeDirectories(config, lang);
+ if (!fsIncludes.empty()) {
+ this->LocalGenerator->AppendIncludeDirectories(
+ includes, cm::remove_BT(fsIncludes), source);
+ *this->FlagFileStream
+ << "# Custom include directories (File Set '" << fileSet->GetName()
+ << "'): " << relativeObj
+ << "_INCLUDE_DIRECTORIES = " << cmList::to_string(fsIncludes) << "\n"
+ << "\n";
+ }
+ }
+
+ // Add include directories from source file properties.
std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (cmValue cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
std::string const& evaluatedIncludes =
@@ -864,6 +869,21 @@
<< "\n";
}
+ // Add file set preprocessor definitions
+ if (fileSet) {
+ auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileDefinitions(config, lang)
+ : fileSet->GetInterfaceCompileDefinitions(config, lang);
+ if (!fsDefines.empty()) {
+ this->LocalGenerator->AppendDefines(defines, fsDefines);
+ *this->FlagFileStream << "# Custom defines (File Set '"
+ << fileSet->GetName() << "'): " << relativeObj
+ << "_DEFINES = " << cmList::to_string(fsDefines)
+ << "\n"
+ << "\n";
+ }
+ }
+
// Get the output paths for source and object files.
std::string const sourceFile = this->LocalGenerator->ConvertToOutputFormat(
source.GetFullPath(), cmOutputConverter::SHELL);
@@ -1464,9 +1484,9 @@
<< "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
/* clang-format on */
for (auto const& pi : this->MultipleOutputPairs) {
- *this->InfoFileStream
- << " " << cmOutputConverter::EscapeForCMake(pi.first) << " "
- << cmOutputConverter::EscapeForCMake(pi.second) << "\n";
+ *this->InfoFileStream << " " << cmScriptGenerator::Quote(pi.first)
+ << ' ' << cmScriptGenerator::Quote(pi.second)
+ << '\n';
}
*this->InfoFileStream << " )\n\n";
}
@@ -1948,8 +1968,8 @@
}
auto const ispcAdditionalObjs =
this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
- for (std::string const& obj : ispcAdditionalObjs) {
- helper.Feed(obj);
+ for (auto const& obj : ispcAdditionalObjs) {
+ helper.Feed(obj.second);
}
helper.Done();
}
@@ -2329,9 +2349,12 @@
responseFlag = "@";
}
std::string const name = cmStrCat("includes_", lang, ".rsp");
- std::string const arg = std::move(responseFlag) +
- this->CreateResponseFile(name, includeFlags, this->FlagFileDepends[lang],
- lang);
+ std::string const includes_rsp = this->CreateResponseFile(
+ name, includeFlags, this->FlagFileDepends[lang], lang);
+ std::string const arg =
+ cmStrCat(std::move(responseFlag),
+ this->LocalGenerator->ConvertToOutputFormat(
+ includes_rsp, cmOutputConverter::SHELL));
this->LocalGenerator->AppendFlags(flags, arg);
} else {
this->LocalGenerator->AppendFlags(flags, includeFlags);
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index e19f4ef..35764d4 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -10,6 +10,7 @@
#include <cmext/string_view>
#include "cmConfigureLog.h"
+#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
@@ -57,7 +58,7 @@
mf.DisplayStatus(IndentText(std::move(text), mf), -1);
} else {
mf.GetMessenger()->DisplayMessage(
- MessageType::AUTHOR_WARNING,
+ MessageType::AUTHOR_WARNING, cmDiagnostics::CMD_NONE,
cmStrCat("Ignored "_s, what, " without CHECK_START"_s),
mf.GetBacktrace());
}
@@ -113,16 +114,20 @@
level = Message::LogLevel::LOG_WARNING;
++i;
} else if (*i == "AUTHOR_WARNING") {
- if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
- !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
- fatal = true;
- type = MessageType::AUTHOR_ERROR;
- level = Message::LogLevel::LOG_ERROR;
- } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
- type = MessageType::AUTHOR_WARNING;
- level = Message::LogLevel::LOG_WARNING;
- } else {
- return true;
+ switch (mf.GetDiagnosticAction(cmDiagnostics::CMD_AUTHOR)) {
+ case cmDiagnostics::Ignore:
+ return true;
+ case cmDiagnostics::FatalError:
+ fatal = true;
+ CM_FALLTHROUGH;
+ case cmDiagnostics::SendError:
+ type = MessageType::AUTHOR_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
+ break;
+ default:
+ type = MessageType::AUTHOR_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
+ break;
}
++i;
} else if (*i == "CHECK_START") {
@@ -158,16 +163,20 @@
level = Message::LogLevel::LOG_TRACE;
++i;
} else if (*i == "DEPRECATION") {
- if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) {
- fatal = true;
- type = MessageType::DEPRECATION_ERROR;
- level = Message::LogLevel::LOG_ERROR;
- } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") ||
- mf.IsOn("CMAKE_WARN_DEPRECATED")) {
- type = MessageType::DEPRECATION_WARNING;
- level = Message::LogLevel::LOG_WARNING;
- } else {
- return true;
+ switch (mf.GetDiagnosticAction(cmDiagnostics::CMD_DEPRECATED)) {
+ case cmDiagnostics::Ignore:
+ return true;
+ case cmDiagnostics::FatalError:
+ fatal = true;
+ CM_FALLTHROUGH;
+ case cmDiagnostics::SendError:
+ type = MessageType::DEPRECATION_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
+ break;
+ default:
+ type = MessageType::DEPRECATION_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
+ break;
}
++i;
} else if (*i == "NOTICE") {
@@ -194,7 +203,8 @@
case Message::LogLevel::LOG_ERROR:
case Message::LogLevel::LOG_WARNING:
// we've overridden the message type, above, so display it directly
- mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace());
+ mf.GetMessenger()->DisplayMessage(type, cmDiagnostics::CMD_NONE, message,
+ mf.GetBacktrace());
break;
case Message::LogLevel::LOG_NOTICE:
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index ad439cb..8e6ffeb 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -2,9 +2,14 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmMessenger.h"
+#include <algorithm>
+#include <sstream>
+#include <utility>
+
#include "cmDocumentationFormatter.h"
#include "cmMessageMetadata.h"
#include "cmMessageType.h"
+#include "cmStateSnapshot.h"
#include "cmStdIoTerminal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -15,9 +20,6 @@
# include "cmSarifLog.h"
#endif
-#include <sstream>
-#include <utility>
-
#ifdef CMake_ENABLE_DEBUGGER
# include "cmDebuggerAdapter.h"
#endif
@@ -46,6 +48,14 @@
return "Warning";
}
+std::string getDiagnosticCategoryStr(cmDiagnosticCategory category)
+{
+ std::string out = cmSystemTools::LowerCase(
+ cmDiagnostics::GetCategoryString(category).substr(4));
+ std::replace(out.begin(), out.end(), '_', '-');
+ return out;
+}
+
cm::StdIo::TermAttr getMessageColor(MessageType t)
{
switch (t) {
@@ -69,23 +79,34 @@
formatter.PrintFormatted(msg, text);
}
-void displayMessage(MessageType t, std::ostringstream& msg)
+void displayMessage(MessageType type, cmDiagnosticCategory category,
+ std::ostringstream& msg)
{
// Add a note about warning suppression.
- if (t == MessageType::AUTHOR_WARNING) {
+ if (type == MessageType::AUTHOR_WARNING) {
msg << "This warning is for project developers. Use -Wno-dev to suppress "
"it.";
- } else if (t == MessageType::AUTHOR_ERROR) {
+ } else if (type == MessageType::AUTHOR_ERROR) {
msg << "This error is for project developers. Use -Wno-error=dev to "
"suppress it.";
}
+ if (category == cmDiagnostics::CMD_AUTHOR) {
+ // Add a note about warning suppression.
+ if (type == MessageType::WARNING) {
+ msg << "This warning is for project developers. "
+ "Use -Wno-author to suppress it.";
+ } else if (type == MessageType::FATAL_ERROR) {
+ msg << "This error is for project developers. "
+ "Use -Wno-error=author to suppress it.";
+ }
+ }
// Add a terminating blank line.
msg << '\n';
#if !defined(CMAKE_BOOTSTRAP)
// Add a C++ stack trace to internal errors.
- if (t == MessageType::INTERNAL_ERROR) {
+ if (type == MessageType::INTERNAL_ERROR) {
std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
if (!stack.empty()) {
if (cmHasLiteralPrefix(stack, "WARNING:")) {
@@ -98,9 +119,11 @@
// Output the message.
cmMessageMetadata md;
- md.attrs = getMessageColor(t);
- if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
- t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
+ md.attrs = getMessageColor(type);
+ if (type == MessageType::FATAL_ERROR ||
+ type == MessageType::INTERNAL_ERROR ||
+ type == MessageType::DEPRECATION_ERROR ||
+ type == MessageType::AUTHOR_ERROR) {
cmSystemTools::SetErrorOccurred();
md.title = "Error";
} else {
@@ -197,17 +220,45 @@
}
if (force || this->IsMessageTypeVisible(t)) {
- this->DisplayMessage(t, text, backtrace);
+ this->DisplayMessage(t, cmDiagnostics::CMD_NONE, text, backtrace);
}
}
-void cmMessenger::DisplayMessage(MessageType t, std::string const& text,
+void cmMessenger::IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& text,
+ cmStateSnapshot const& context,
+ cmListFileBacktrace const& backtrace) const
+{
+ cmDiagnosticAction const action = context.GetDiagnostic(category);
+ switch (action) {
+ case cmDiagnostics::FatalError:
+ cmSystemTools::SetFatalErrorOccurred();
+ CM_FALLTHROUGH;
+ case cmDiagnostics::SendError:
+ cmSystemTools::SetErrorOccurred();
+ this->DisplayMessage(MessageType::FATAL_ERROR, category, text,
+ backtrace);
+ break;
+ case cmDiagnostics::Warn:
+ this->DisplayMessage(MessageType::WARNING, category, text, backtrace);
+ break;
+ default:
+ return;
+ }
+}
+
+void cmMessenger::DisplayMessage(MessageType type,
+ cmDiagnosticCategory category,
+ std::string const& text,
cmListFileBacktrace const& backtrace) const
{
std::ostringstream msg;
// Print the message preamble.
- msg << "CMake " << getMessageTypeStr(t);
+ msg << "CMake " << getMessageTypeStr(type);
+ if (category != cmDiagnostics::CMD_NONE) {
+ msg << " (" << getDiagnosticCategoryStr(category) << ')';
+ }
// Add the immediate context.
this->PrintBacktraceTitle(msg, backtrace);
@@ -217,16 +268,16 @@
// Add the rest of the context.
PrintCallStack(msg, backtrace, this->TopSource);
- displayMessage(t, msg);
+ displayMessage(type, category, msg);
#ifndef CMAKE_BOOTSTRAP
// Add message to SARIF logs
- this->SarifLog.LogMessage(t, text, backtrace);
+ this->SarifLog.LogMessage(type, text, backtrace);
#endif
#ifdef CMake_ENABLE_DEBUGGER
if (DebuggerAdapter) {
- DebuggerAdapter->OnMessageOutput(t, msg.str());
+ DebuggerAdapter->OnMessageOutput(type, msg.str());
}
#endif
}
diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h
index ad04b77..4f5d170 100644
--- a/Source/cmMessenger.h
+++ b/Source/cmMessenger.h
@@ -10,6 +10,7 @@
#include <cm/optional>
+#include "cmDiagnostics.h"
#include "cmListFileCache.h"
#include "cmMessageType.h" // IWYU pragma: keep
@@ -17,6 +18,8 @@
# include "cmSarifLog.h"
#endif
+class cmStateSnapshot;
+
#ifdef CMake_ENABLE_DEBUGGER
namespace cmDebugger {
class cmDebuggerAdapter;
@@ -27,10 +30,16 @@
{
public:
void IssueMessage(
- MessageType t, std::string const& text,
+ MessageType type, std::string const& text,
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
- void DisplayMessage(MessageType t, std::string const& text,
+ void IssueDiagnostic(
+ cmDiagnosticCategory category, std::string const& text,
+ cmStateSnapshot const& context,
+ cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
+
+ void DisplayMessage(MessageType type, cmDiagnosticCategory category,
+ std::string const& text,
cmListFileBacktrace const& backtrace) const;
void SetTopSource(cm::optional<std::string> topSource);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index e5cb1c0..e144e8d 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -10,6 +10,7 @@
#include <unordered_set>
#include <utility>
+#include <cm/filesystem>
#include <cm/memory>
#include <cm/optional>
#include <cm/vector>
@@ -479,8 +480,9 @@
}
if (this->TargetLinkLanguage(config) == "Rust") {
- vars.RustSources = "$RUST_SOURCES";
- vars.RustObjectDeps = "$RUST_OBJECT_DEPS";
+ vars.RustMainCrateRoot = "$RUST_MAIN_CRATE_ROOT";
+ vars.RustLinkCrates = "$RUST_LINK_CRATES";
+ vars.RustNativeObjects = "$RUST_NATIVE_OBJECTS";
}
std::string responseFlag;
@@ -1284,46 +1286,61 @@
} else if (this->TargetLinkLanguage(config) == "Rust") {
// Use one-step build/link for Rust.
// Compute specific libraries to link with.
- std::vector<cmSourceFile const*> sources;
- gt->GetObjectSources(sources, config);
cmLocalGenerator const* lg = this->GetLocalGenerator();
- std::string entry_obj;
-
- for (auto const& source : sources) {
- if (source->GetLanguage() == "Rust") {
- if (vars.count("RUST_SOURCES") == 0) {
- std::string const sourcePath =
- this->GetCompiledSourceNinjaPath(source);
- vars["RUST_SOURCES"] =
- lg->ConvertToOutputFormat(sourcePath, cmOutputConverter::SHELL);
- entry_obj = this->GetObjectFilePath(source, config);
- } else {
- assert(false && "Rust crate can only have 1 entry");
- }
- }
- }
linkBuild.ExplicitDeps = this->GetObjects(config);
- std::stringstream obj_deps;
- // Do not try linking to object file created from the crate entry.
+ // First we handle Rust rlib and normal native objects.
+ std::stringstream rlibs;
+ std::stringstream objects;
for (auto const& obj : linkBuild.ExplicitDeps) {
- if (obj != entry_obj) {
- obj_deps << " "
- << lg->ConvertToOutputFormat(obj, cmOutputConverter::SHELL);
+ cm::filesystem::path const objPath(obj);
+ if (objPath.extension() == ".rlib") {
+ // Drop the "lib..." prefix and the ".rs" suffix. The prefix is
+ // required by Rust on the crate rlib file, but is hidden from the user
+ // when using the crate from Rust source code, so we drop it to be
+ // consistent with common usage in Rust.
+ std::string objStem = objPath.stem().string();
+ objStem = objStem.substr(3, objStem.length() - 6);
+ rlibs << " --extern=" << objStem << "="
+ << lg->ConvertToOutputFormat(obj, cmOutputConverter::SHELL);
+ } else {
+ objects << " -Clink-arg="
+ << lg->ConvertToOutputFormat(obj, cmOutputConverter::SHELL);
}
}
+ vars["RUST_LINK_CRATES"] = rlibs.str();
+ vars["RUST_NATIVE_OBJECTS"] = objects.str();
- vars["RUST_OBJECT_DEPS"] = obj_deps.str();
+ // Then, we handle the main crate root that is build as part of the link
+ // step.
+ std::vector<cmSourceFile const*> mainCrateRoot;
+ gt->GetRustMainCrateRoot(mainCrateRoot, config);
+ if (mainCrateRoot.size() != 1) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Target " + gt->GetName() +
+ " has none or more than one main crate root.");
+ return;
+ }
+ std::string mainCrateRootPath =
+ this->GetCompiledSourceNinjaPath(mainCrateRoot[0]);
+ linkBuild.ExplicitDeps.emplace_back(mainCrateRootPath);
+ mainCrateRootPath =
+ lg->ConvertToOutputFormat(mainCrateRootPath, cmOutputConverter::SHELL);
+ vars["RUST_MAIN_CRATE_ROOT"] = mainCrateRootPath;
} else {
linkBuild.ExplicitDeps = this->GetObjects(config);
}
- std::vector<std::string> extraISPCObjects =
+ auto extraISPCObjects =
this->GetGeneratorTarget()->GetGeneratedISPCObjects(config);
- std::transform(extraISPCObjects.begin(), extraISPCObjects.end(),
- std::back_inserter(linkBuild.ExplicitDeps),
- this->MapToNinjaPath());
+ auto const mapToNinjaPath = this->MapToNinjaPath();
+ std::transform(
+ extraISPCObjects.begin(), extraISPCObjects.end(),
+ std::back_inserter(linkBuild.ExplicitDeps),
+ [&mapToNinjaPath](std::pair<cmSourceFile const*, std::string> const& obj)
+ -> std::string { return mapToNinjaPath(obj.second); });
linkBuild.ImplicitDeps =
this->ComputeLinkDeps(this->TargetLinkLanguage(config), config);
@@ -1497,7 +1514,7 @@
std::transform(
ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(globalGen->GetByproductsForCleanTarget()),
- this->MapToNinjaPath());
+ mapToNinjaPath);
}
}
}
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index b2308b5..36a3cad 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -27,9 +27,11 @@
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmDyndepCollation.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
@@ -237,6 +239,18 @@
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
}
+ if (auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ config, source)) {
+ auto options = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileOptions(config, language)
+ : fileSet->GetInterfaceCompileOptions(config, language);
+ if (!options.empty()) {
+ this->LocalGenerator->AppendCompileOptions(flags,
+ cm::remove_BT(options));
+ }
+ }
+
// Add precompile headers compile options.
if (!pchSources.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
@@ -254,7 +268,7 @@
}
auto const* fs = this->GeneratorTarget->GetFileSetForSource(config, source);
- if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
if (source->GetLanguage() != "CXX"_s) {
this->GetMakefile()->IssueMessage(
MessageType::FATAL_ERROR,
@@ -330,6 +344,17 @@
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS));
}
+ if (auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ config, source)) {
+ auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetCompileDefinitions(config, language)
+ : fileSet->GetInterfaceCompileDefinitions(config, language);
+ if (!fsDefines.empty()) {
+ this->LocalGenerator->AppendDefines(defines, fsDefines);
+ }
+ }
+
std::string definesString = this->GetDefines(language, config);
this->LocalGenerator->JoinDefines(defines, definesString, language);
@@ -341,6 +366,19 @@
std::string const& config)
{
std::vector<std::string> includes;
+
+ if (auto const* fileSet =
+ this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
+ config, source)) {
+ auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
+ ? fileSet->GetIncludeDirectories(config, language)
+ : fileSet->GetInterfaceIncludeDirectories(config, language);
+ if (!fsIncludes.empty()) {
+ this->LocalGenerator->AppendIncludeDirectories(
+ includes, cm::remove_BT(fsIncludes), *source);
+ }
+ }
+
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, config, this->GeneratorTarget, language);
@@ -690,6 +728,7 @@
vars.CudaCompileMode = "$CUDA_COMPILE_MODE";
vars.ISPCHeader = "$ISPC_HEADER_FILE";
vars.Config = "$CONFIG";
+ vars.RustEmit = "$RUST_EMIT";
cmMakefile* mf = this->GetMakefile();
@@ -1050,17 +1089,9 @@
// Gather order-only dependencies on custom command outputs.
std::vector<std::string> ccouts;
std::vector<std::string> ccouts_private;
- bool usePrivateGeneratedSources = false;
- if (this->GeneratorTarget->Target->HasFileSets()) {
- switch (this->GetGeneratorTarget()->GetPolicyStatusCMP0154()) {
- case cmPolicies::WARN:
- case cmPolicies::OLD:
- break;
- case cmPolicies::NEW:
- usePrivateGeneratedSources = true;
- break;
- }
- }
+ bool usePrivateGeneratedSources = this->GeneratorTarget->HasFileSets() &&
+ this->GetGeneratorTarget()->GetPolicyStatusCMP0154() == cmPolicies::NEW;
+
for (cmCustomCommand const* cc : customCommands) {
cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator());
std::vector<std::string> const& ccoutputs = ccg.GetOutputs();
@@ -1073,20 +1104,54 @@
// Skip over outputs that were already detected.
std::advance(it, nPreviousOutputs);
while (it != ccouts.end()) {
- cmFileSet const* fileset =
+ cmGeneratorFileSet const* fileset =
this->GeneratorTarget->GetFileSetForSource(
config, this->Makefile->GetOrCreateGeneratedSource(*it));
- bool isVisible = fileset &&
- cmFileSetVisibilityIsForInterface(fileset->GetVisibility());
- bool isIncludeable =
- !fileset || cmFileSetTypeCanBeIncluded(fileset->GetType());
- if (fileset && isVisible && isIncludeable) {
- ++it;
+
+ if (!fileset) {
+ // use private order dependency
+ ccouts_private.push_back(*it);
+ it = ccouts.erase(it);
continue;
}
- if (!fileset || isIncludeable) {
- ccouts_private.push_back(*it);
+
+ using DependencyMode = cm::FileSetMetadata::DependencyMode;
+
+ cmValue independentFiles = fileset->GetProperty("INDEPENDENT_FILES");
+ // retrieve default mode
+ DependencyMode dependencyMode =
+ cm::FileSetMetadata::GetDependencyMode(fileset->GetType());
+ // if property is defined, try to enforce mode requested
+ if (independentFiles) {
+ dependencyMode = cm::FileSetMetadata::GetDependencyMode(
+ fileset->GetType(),
+ independentFiles.IsOn() ? DependencyMode::IndependentFiles
+ : DependencyMode::Includables);
}
+ if (independentFiles.IsOn() &&
+ dependencyMode != DependencyMode::IndependentFiles) {
+ // requested dependency mode not supported
+ this->GetMakefile()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(R"(the "INDEPENDENT_FILES" property of the file set ")",
+ fileset->GetName(), R"(" of the target ")",
+ this->GeneratorTarget->GetName(),
+ R"(" will be ignored because it is incompatible with )"
+ R"(the file set type ")",
+ fileset->GetType(), R"(".)"));
+ }
+ if (dependencyMode == DependencyMode::Includables) {
+ if (fileset->IsForInterface()) {
+ // use public order dependency
+ ++it;
+ } else {
+ // use private order dependency
+ ccouts_private.push_back(*it);
+ it = ccouts.erase(it);
+ }
+ continue;
+ }
+ // no order dependency is required
it = ccouts.erase(it);
}
}
@@ -1185,12 +1250,12 @@
std::vector<cmSourceFile*> sources;
this->GeneratorTarget->GetSourceFiles(sources, config);
for (cmSourceFile const* sf : sources) {
- cmFileSet const* fs =
+ cmGeneratorFileSet const* fs =
this->GeneratorTarget->GetFileSetForSource(config, sf);
if (!fs) {
continue;
}
- if (fs->GetType() != "CXX_MODULES"_s) {
+ if (fs->GetType() != cm::FileSetMetadata::CXX_MODULES) {
continue;
}
if (sf->GetLanguage().empty()) {
@@ -1198,8 +1263,8 @@
MessageType::FATAL_ERROR,
cmStrCat("Target \"", this->GeneratorTarget->GetName(),
"\" has source file\n ", sf->GetFullPath(),
- "\nin a \"FILE_SET TYPE CXX_MODULES\" but it is not "
- "scheduled for compilation."));
+ "\nin a \"FILE_SET TYPE ", cm::FileSetMetadata::CXX_MODULES,
+ "\" but it is not scheduled for compilation."));
}
}
}
@@ -1249,6 +1314,23 @@
this->WriteTargetDependInfo(language, config);
+ // Non-imported synthetic targets read module info from their native target
+ // Add as implicit dependency.
+ if (this->GeneratorTarget->IsSynthetic()) {
+ if (cmGeneratorTarget const* native_gt =
+ this->LocalGenerator->FindGeneratorTargetToUse(
+ this->GeneratorTarget->Target->GetTemplateName())) {
+ if (!native_gt->IsImported()) {
+ std::string native_dir = native_gt->GetSupportDirectory();
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
+ native_dir = cmStrCat(native_dir, '/', config);
+ }
+ build.ImplicitDeps.emplace_back(this->ConvertToNinjaPath(
+ cmStrCat(native_dir, '/', language, "Modules.json")));
+ }
+ }
+ }
+
auto const linked_directories =
this->GetLinkedTargetDirectories(language, config);
for (std::string const& l : linked_directories.Direct) {
@@ -1739,6 +1821,11 @@
}
}
+ if (language == "Rust") {
+ cmValue const rustEmit = source->GetRustEmitProperty();
+ vars["RUST_EMIT"] = rustEmit;
+ }
+
if (language == "Swift") {
this->EmitSwiftDependencyInfo(source, config);
} else {
@@ -2172,6 +2259,22 @@
tdi_forward_modules_from_target_dirs.append(l);
}
+ // Record the native target support directory for non-imported synthetic
+ // targets
+ if (this->GeneratorTarget->IsSynthetic()) {
+ if (cmGeneratorTarget* nativeGT =
+ this->LocalGenerator->FindGeneratorTargetToUse(
+ this->GeneratorTarget->Target->GetTemplateName())) {
+ if (!nativeGT->IsImported()) {
+ std::string nativeDir = nativeGT->GetSupportDirectory();
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
+ nativeDir = cmStrCat(nativeDir, '/', config);
+ }
+ tdi["native-target-dir"] = nativeDir;
+ }
+ }
+ }
+
cmDyndepGeneratorCallbacks cb;
cb.ObjectFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
return this->GetObjectFilePath(sf, cnf);
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index c72dbe4..6826b67 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -155,44 +155,36 @@
}
std::string cmOutputConverter::ConvertToOutputForExisting(
- std::string const& remote, OutputFormat format, bool useWatcomQuote) const
+ cm::string_view path, OutputFormat format, bool useWatcomQuote) const
{
#ifdef _WIN32
- // Cache the Short Paths since we only convert the same few paths anyway and
- // calling `GetShortPathNameW` is really expensive.
+ // Cache the short paths since `GetShortPathNameW` is really expensive.
static std::unordered_map<std::string, std::string> shortPathCache{};
- // If this is a windows shell, the result has a space, and the path
- // already exists, we can use a short-path to reference it without a
- // space.
+ // If this is a windows shell, the path has a space, and the path already
+ // exists, we can use a short-path to reference it without a space.
if (this->GetState()->UseWindowsShell() &&
- remote.find_first_of(" #") != std::string::npos &&
- cmSystemTools::FileExists(remote)) {
-
- std::string shortPath = [&]() {
- auto cachedShortPathIt = shortPathCache.find(remote);
-
- if (cachedShortPathIt != shortPathCache.end()) {
- return cachedShortPathIt->second;
+ path.find_first_of(" #") != std::string::npos) {
+ auto origPath = std::string(path);
+ if (cmSystemTools::FileExists(origPath)) {
+ auto i = shortPathCache.find(origPath);
+ if (i == shortPathCache.end()) {
+ std::string shortPath;
+ if (!cmSystemTools::GetShortPath(origPath, shortPath)) {
+ // Fallback for cases when Windows refuses to resolve
+ // the short path, like for `C:\Program Files\WindowsApps\...`.
+ shortPath = origPath;
+ }
+ i = shortPathCache.emplace(std::move(origPath), std::move(shortPath))
+ .first;
}
-
- std::string 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;
- }();
-
- return this->ConvertToOutputFormat(shortPath, format, useWatcomQuote);
+ path = i->second;
+ }
}
#endif
// Otherwise, perform standard conversion.
- return this->ConvertToOutputFormat(remote, format, useWatcomQuote);
+ return this->ConvertToOutputFormat(path, format, useWatcomQuote);
}
std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 6f6374c..35877f3 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -54,7 +54,7 @@
std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;
//! for existing files convert to output path and short path if spaces
- std::string ConvertToOutputForExisting(std::string const& remote,
+ std::string ConvertToOutputForExisting(cm::string_view path,
OutputFormat format = SHELL,
bool useWatcomQuote = false) const;
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 337f220..0c308fb 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -259,10 +259,10 @@
minPatch > maxPatch) ||
(minMajor == maxMajor && minMinor == maxMinor &&
minPatch == maxPatch && minTweak > maxTweak)) {
- mf->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Policy VERSION range \"", version_min, "...", version_max,
- "\" specifies a larger minimum than maximum."));
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("Policy VERSION range \"", version_min, "...",
+ version_max,
+ "\" specifies a later minimum than maximum."));
return false;
}
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 8afb04b..a9ddf9e 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -629,7 +629,17 @@
4, 3, 0, WARN) \
SELECT(POLICY, CMP0210, \
"CMAKE_<LANG>_LINK_FLAGS adds link flags to all target types.", 4, \
- 3, 0, WARN)
+ 3, 0, WARN) \
+ SELECT(POLICY, CMP0211, \
+ "A file may belong to at most one file set in a target.", 4, 4, 0, \
+ WARN) \
+ SELECT(POLICY, CMP0212, \
+ "add_custom_command DEPENDS does not strip .exe suffixes.", 4, 4, 0, \
+ WARN) \
+ SELECT(POLICY, CMP0213, \
+ "file(ARCHIVE_{CREATE,EXTRACT}) encode archive paths as UTF-8 by " \
+ "default.", \
+ 4, 4, 0, WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -684,11 +694,13 @@
F(CMP0203) \
F(CMP0204) \
F(CMP0209) \
- F(CMP0210)
+ F(CMP0210) \
+ F(CMP0211)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
F(CMP0116) \
- F(CMP0147)
+ F(CMP0147) \
+ F(CMP0212)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index cdba0c9..05b8a51 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -1372,7 +1372,8 @@
auto const& gen = this->GlobalGen->GetName();
return this->QtVersion >= IntegerVersion(5, 15) &&
(gen.find("Ninja") != std::string::npos ||
- gen.find("Make") != std::string::npos);
+ gen.find("Make") != std::string::npos ||
+ gen.find("Visual Studio") != std::string::npos || gen == "Xcode");
}();
// Files provided by the autogen target
@@ -1453,6 +1454,10 @@
if (this->AutogenTarget.GlobalTarget) {
usePRE_BUILD = false;
}
+ // Cannot use PRE_BUILD with depfiles
+ if (useDepfile) {
+ usePRE_BUILD = false;
+ }
}
// Create the autogen target/command
if (usePRE_BUILD) {
@@ -1994,7 +1999,7 @@
info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);
- EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;
+ cm::EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;
if (this->MultiConfig) {
for (auto const& cfg : this->ConfigsList) {
@@ -2003,10 +2008,10 @@
cmGeneratorExpressionDAGChecker dagChecker{
this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr, context,
};
- AddInterfaceEntries(this->GenTarget, "INTERFACE_AUTOMOC_MACRO_NAMES",
- context, &dagChecker,
- InterfaceAutoMocMacroNamesEntries,
- IncludeRuntimeInterface::Yes);
+ cm::AddInterfaceEntries(
+ this->GenTarget, "INTERFACE_AUTOMOC_MACRO_NAMES", context,
+ &dagChecker, InterfaceAutoMocMacroNamesEntries,
+ cm::IncludeRuntimeInterface::Yes);
}
}
} else {
@@ -2016,7 +2021,7 @@
};
AddInterfaceEntries(
this->GenTarget, "INTERFACE_AUTOMOC_MACRO_NAMES", context, &dagChecker,
- InterfaceAutoMocMacroNamesEntries, IncludeRuntimeInterface::Yes);
+ InterfaceAutoMocMacroNamesEntries, cm::IncludeRuntimeInterface::Yes);
}
for (auto const& entry : InterfaceAutoMocMacroNamesEntries.Entries) {
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 8561425..95dc5a9 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -2116,8 +2116,11 @@
this->Log().Info(GenT::MOC, result.StdOut);
}
- // Extract dependencies from the dep file moc generated for us
- if (this->MocConst().CanOutputDependencies) {
+ // Extract dependencies from the dep file moc generated for us.
+ // When a build-system depfile is used, JobDepFilesMergeT handles reading
+ // and merging all moc dependencies, so skip per-compilation dep reading.
+ if (this->MocConst().CanOutputDependencies &&
+ this->BaseConst().DepFile.empty()) {
std::string const depfile = outputFile + ".d";
if (this->Log().Verbose()) {
this->Log().Info(
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index 83eef77..7f9f0c3 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -11,13 +11,26 @@
cmRulePlaceholderExpander::cmRulePlaceholderExpander(
cmBuildStep buildStep, std::map<std::string, std::string> compilers,
std::map<std::string, std::string> variableMappings,
- std::string compilerSysroot, std::string linkerSysroot)
+ std::string compilerSysroot, std::string linkerSysroot,
+ UseShortPaths useShortPaths)
: BuildStep(buildStep)
, Compilers(std::move(compilers))
, VariableMappings(std::move(variableMappings))
, CompilerSysroot(std::move(compilerSysroot))
, LinkerSysroot(std::move(linkerSysroot))
{
+ if (useShortPaths == UseShortPaths::Yes) {
+ this->ConvertToOutputForExisting =
+ [this](cm::string_view path) -> std::string {
+ return this->OutputConverter->ConvertToOutputForExisting(path);
+ };
+ } else {
+ this->ConvertToOutputForExisting =
+ [this](cm::string_view path) -> std::string {
+ return this->OutputConverter->ConvertToOutputFormat(
+ path, cmOutputConverter::SHELL);
+ };
+ }
}
std::string cmRulePlaceholderExpander::ExpandVariable(
@@ -30,8 +43,8 @@
}
if (this->ReplaceValues->Linker) {
if (variable == "CMAKE_LINKER") {
- auto result = this->OutputConverter->ConvertToOutputForExisting(
- this->ReplaceValues->Linker);
+ auto result =
+ this->ConvertToOutputForExisting(this->ReplaceValues->Linker);
if (this->ReplaceValues->Launcher) {
// Add launcher as part of expansion so that it always appears
// immediately before the command itself, regardless of whether the
@@ -143,14 +156,24 @@
return this->ReplaceValues->SwiftSources;
}
}
- if (this->ReplaceValues->RustSources) {
- if (variable == "RUST_SOURCES") {
- return this->ReplaceValues->RustSources;
+ if (this->ReplaceValues->RustEmit) {
+ if (variable == "RUST_EMIT") {
+ return this->ReplaceValues->RustEmit;
}
}
- if (this->ReplaceValues->RustObjectDeps) {
- if (variable == "RUST_OBJECT_DEPS") {
- return this->ReplaceValues->RustObjectDeps;
+ if (this->ReplaceValues->RustMainCrateRoot) {
+ if (variable == "RUST_MAIN_CRATE_ROOT") {
+ return this->ReplaceValues->RustMainCrateRoot;
+ }
+ }
+ if (this->ReplaceValues->RustLinkCrates) {
+ if (variable == "RUST_LINK_CRATES") {
+ return this->ReplaceValues->RustLinkCrates;
+ }
+ }
+ if (this->ReplaceValues->RustNativeObjects) {
+ if (variable == "RUST_NATIVE_OBJECTS") {
+ return this->ReplaceValues->RustNativeObjects;
}
}
if (this->ReplaceValues->TargetPDB) {
@@ -301,8 +324,9 @@
auto compIt = this->Compilers.find(variable);
if (compIt != this->Compilers.end()) {
- std::string ret = this->OutputConverter->ConvertToOutputForExisting(
- this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
+ std::string const& compilerPath =
+ this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"];
+ std::string ret = this->ConvertToOutputForExisting(compilerPath);
std::string const& compilerArg1 =
this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_ARG1"];
std::string const& compilerTarget =
@@ -365,7 +389,7 @@
auto mapIt = this->VariableMappings.find(variable);
if (mapIt != this->VariableMappings.end()) {
if (variable.find("_FLAG") == std::string::npos) {
- return this->OutputConverter->ConvertToOutputForExisting(mapIt->second);
+ return this->ConvertToOutputForExisting(mapIt->second);
}
return mapIt->second;
}
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 4b44c64..60fc8f8 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -5,9 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <map>
#include <string>
+#include <cm/string_view>
+
#include "cmGeneratorOptions.h"
#include "cmPlaceholderExpander.h"
@@ -16,10 +19,17 @@
class cmRulePlaceholderExpander : public cmPlaceholderExpander
{
public:
+ enum class UseShortPaths
+ {
+ No,
+ Yes,
+ };
+
cmRulePlaceholderExpander(
cmBuildStep buildStep, std::map<std::string, std::string> compilers,
std::map<std::string, std::string> variableMappings,
- std::string compilerSysroot, std::string linkerSysroot);
+ std::string compilerSysroot, std::string linkerSysroot,
+ UseShortPaths useShortPaths);
void SetTargetImpLib(std::string const& targetImpLib)
{
@@ -69,8 +79,10 @@
char const* SwiftModuleName = nullptr;
char const* SwiftOutputFileMapOption = nullptr;
char const* SwiftSources = nullptr;
- char const* RustSources = nullptr;
- char const* RustObjectDeps = nullptr;
+ char const* RustEmit = nullptr;
+ char const* RustMainCrateRoot = nullptr;
+ char const* RustLinkCrates = nullptr;
+ char const* RustNativeObjects = nullptr;
char const* ISPCHeader = nullptr;
char const* CudaCompileMode = nullptr;
char const* Fatbinary = nullptr;
@@ -95,6 +107,7 @@
std::map<std::string, std::string> VariableMappings;
std::string CompilerSysroot;
std::string LinkerSysroot;
+ std::function<std::string(cm::string_view)> ConvertToOutputForExisting;
cmOutputConverter* OutputConverter = nullptr;
RuleVariables const* ReplaceValues = nullptr;
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index b3dff8b..5efc243 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -3,11 +3,55 @@
#include "cmScriptGenerator.h"
#include <algorithm>
+#include <cstddef>
+#include <sstream>
#include <utility>
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+namespace {
+
+int RequiredBracketLength(cm::string_view s)
+{
+ for (int n = 0;; ++n) {
+ std::string const needle = "]" + std::string(n, '=');
+
+ bool ok = true;
+ std::size_t pos = s.find(needle);
+ while (pos != cm::string_view::npos) {
+ std::size_t const next = pos + needle.size();
+ if (next == s.size() || s[next] == ']') {
+ ok = false;
+ break;
+ }
+ pos = s.find(needle, pos + 1);
+ }
+
+ if (ok) {
+ return n;
+ }
+ }
+}
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& os, cmScriptGeneratorQuoted const& self)
+{
+ if (self.BracketLength == -1) {
+ return os << '"' << self.Value << '"';
+ }
+ auto const sep = std::string(self.BracketLength, '=');
+ return os << '[' << sep << '[' << self.Value << ']' << sep << ']';
+}
+
+std::string cmScriptGeneratorQuoted::str() const
+{
+ std::stringstream out;
+ out << *this;
+ return out.str();
+}
+
cmScriptGenerator::cmScriptGenerator(std::string config_var,
std::vector<std::string> configurations)
: RuntimeConfigVariable(std::move(config_var))
@@ -28,6 +72,14 @@
this->ConfigurationTypes = nullptr;
}
+cmScriptGeneratorQuoted cmScriptGenerator::Quote(cm::string_view value)
+{
+ if (value.find_first_of("\"$\\") == std::string::npos) {
+ return cmScriptGeneratorQuoted(value, -1);
+ }
+ return cmScriptGeneratorQuoted(value, RequiredBracketLength(value));
+}
+
static void cmScriptGeneratorEncodeConfig(std::string const& config,
std::string& result)
{
diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h
index 616817b..2a6ff4d 100644
--- a/Source/cmScriptGenerator.h
+++ b/Source/cmScriptGenerator.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
class cmScriptGeneratorIndent
{
public:
@@ -37,6 +39,26 @@
return os;
}
+class cmScriptGeneratorQuoted
+{
+public:
+ cmScriptGeneratorQuoted(cm::string_view value, int bracket_length)
+ : Value(value)
+ , BracketLength(bracket_length)
+ {
+ }
+
+ std::string str() const;
+ operator std::string() const { return str(); }
+
+private:
+ friend std::ostream& operator<<(std::ostream& os,
+ cmScriptGeneratorQuoted const& self);
+
+ cm::string_view Value;
+ int BracketLength;
+};
+
/** \class cmScriptGenerator
* \brief Support class for generating install and test scripts.
*
@@ -54,6 +76,8 @@
void Generate(std::ostream& os, std::string const& config,
std::vector<std::string> const& configurationTypes);
+ static cmScriptGeneratorQuoted Quote(cm::string_view value);
+
protected:
using Indent = cmScriptGeneratorIndent;
virtual void GenerateScript(std::ostream& os);
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 5f2cf3b..3325eee 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -503,3 +503,13 @@
{
this->CustomCommand = std::move(cc);
}
+
+cmValue cmSourceFile::GetRustEmitProperty() const
+{
+ static std::string const s_default = "link";
+ cmValue const value = this->GetProperty("Rust_EMIT");
+ if (!value || value->empty()) {
+ return cmValue(s_default);
+ }
+ return value;
+}
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index d951793..0d9bc2e 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -184,6 +184,8 @@
void SetObjectLibrary(std::string const& objlib);
std::string GetObjectLibrary() const;
+ cmValue GetRustEmitProperty() const;
+
private:
cmSourceFileLocation Location;
cmPropertyMap Properties;
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 3255650..76d0741 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -14,6 +14,7 @@
#include "cmCacheManager.h"
#include "cmDefinitions.h"
+#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmGlobCacheEntry.h" // IWYU pragma: keep
#include "cmGlobVerificationManager.h"
@@ -274,8 +275,12 @@
this->CacheManager->RemoveCacheEntryProperty(key, propertyName);
}
-cmStateSnapshot cmState::Reset()
+cmStateSnapshot cmState::Reset(cmStateSnapshot const& diagnosticState)
{
+ assert(diagnosticState.CanPopDiagnosticScope());
+ cmDiagnostics::DiagnosticMap diagnostics =
+ *diagnosticState.Position->Diagnostics;
+
this->GlobalProperties.Clear();
this->PropertyDefinitions = {};
this->GlobVerificationManager->Reset();
@@ -301,6 +306,15 @@
assert(pos->Policies.IsValid());
assert(pos->PolicyRoot.IsValid());
+ this->DiagnosticStack.Clear();
+ pos->Diagnostics = this->DiagnosticStack.Push(this->DiagnosticStack.Root(),
+ { diagnostics, false });
+ pos->DiagnosticRoot = this->DiagnosticStack.Root();
+ pos->DiagnosticScope = this->DiagnosticStack.Root();
+ assert(pos->Diagnostics.IsValid());
+ assert(pos->DiagnosticRoot.IsValid());
+ assert(pos->Diagnostics != pos->DiagnosticRoot);
+
{
std::string srcDir =
*cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
@@ -886,6 +900,13 @@
pos->PolicyScope = this->PolicyStack.Root();
assert(pos->Policies.IsValid());
assert(pos->PolicyRoot.IsValid());
+ pos->Diagnostics =
+ this->DiagnosticStack.Push(this->DiagnosticStack.Root(), { {}, false });
+ pos->DiagnosticRoot = this->DiagnosticStack.Root();
+ pos->DiagnosticScope = this->DiagnosticStack.Root();
+ assert(pos->Diagnostics.IsValid());
+ assert(pos->DiagnosticRoot.IsValid());
+ assert(pos->Diagnostics != pos->DiagnosticRoot);
pos->Vars = this->VarTree.Push(this->VarTree.Root());
assert(pos->Vars.IsValid());
pos->Parent = this->VarTree.Root();
@@ -913,6 +934,11 @@
pos->PolicyScope = originSnapshot.Position->Policies;
assert(pos->Policies.IsValid());
assert(pos->PolicyRoot.IsValid());
+ pos->Diagnostics = originSnapshot.Position->Diagnostics;
+ pos->DiagnosticRoot = originSnapshot.Position->Diagnostics;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
+ assert(pos->Diagnostics.IsValid());
+ assert(pos->DiagnosticRoot.IsValid());
cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
pos->Parent = origin;
@@ -939,6 +965,7 @@
assert(originSnapshot.Position->Vars.IsValid());
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
return { this, pos };
}
@@ -954,6 +981,7 @@
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
assert(originSnapshot.Position->Vars.IsValid());
cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
pos->Parent = origin;
@@ -973,6 +1001,7 @@
assert(originSnapshot.Position->Vars.IsValid());
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
return { this, pos };
}
@@ -988,6 +1017,7 @@
assert(originSnapshot.Position->Vars.IsValid());
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
return { this, pos };
}
@@ -1001,6 +1031,7 @@
pos->Keep = false;
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
assert(originSnapshot.Position->Vars.IsValid());
cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
@@ -1021,6 +1052,7 @@
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
return { this, pos };
}
@@ -1033,6 +1065,7 @@
pos->Keep = false;
pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
+ pos->DiagnosticScope = originSnapshot.Position->Diagnostics;
return { this, pos };
}
diff --git a/Source/cmState.h b/Source/cmState.h
index 885ade5..a25342f 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -138,7 +138,6 @@
std::string& value,
cmStateEnums::CacheEntryType& type);
- cmStateSnapshot Reset();
// Define a property
void DefineProperty(std::string const& name, cmProperty::ScopeType scope,
std::string const& ShortDescription,
@@ -260,6 +259,8 @@
private:
friend class cmake;
+ cmStateSnapshot Reset(cmStateSnapshot const& diagnosticState);
+
void AddCacheEntry(std::string const& key, cmValue value,
std::string const& helpString,
cmStateEnums::CacheEntryType type);
@@ -288,6 +289,7 @@
cmLinkedTree<std::string> ExecutionListFiles;
+ cmLinkedTree<cmStateDetail::DiagnosticStackEntry> DiagnosticStack;
cmLinkedTree<cmStateDetail::PolicyStackEntry> PolicyStack;
cmLinkedTree<cmStateDetail::SnapshotDataType> SnapshotData;
cmLinkedTree<cmDefinitions> VarTree;
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index 651d993..3c7655e 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -11,6 +11,7 @@
#include <vector>
#include "cmDefinitions.h"
+#include "cmDiagnostics.h"
#include "cmLinkedTree.h"
#include "cmListFileCache.h"
#include "cmPackageState.h"
@@ -22,6 +23,7 @@
namespace cmStateDetail {
struct BuildsystemDirectoryStateType;
struct PolicyStackEntry;
+struct DiagnosticStackEntry;
extern std::string const PropertySentinel;
} // namespace cmStateDetail
@@ -32,6 +34,9 @@
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator Policies;
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator PolicyRoot;
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator PolicyScope;
+ cmLinkedTree<cmStateDetail::DiagnosticStackEntry>::iterator Diagnostics;
+ cmLinkedTree<cmStateDetail::DiagnosticStackEntry>::iterator DiagnosticRoot;
+ cmLinkedTree<cmStateDetail::DiagnosticStackEntry>::iterator DiagnosticScope;
cmStateEnums::SnapshotType SnapshotType;
cmStateEnums::SnapshotUnwindType UnwindType = cmStateEnums::NO_UNWIND;
cmStateEnums::SnapshotUnwindState UnwindState = cmStateEnums::NOT_UNWINDING;
@@ -64,6 +69,22 @@
bool Weak;
};
+struct cmStateDetail::DiagnosticStackEntry
+ : public cmDiagnostics::DiagnosticMap
+{
+ using derived = cmDiagnostics::DiagnosticMap;
+ DiagnosticStackEntry(bool w = false)
+ : Weak(w)
+ {
+ }
+ DiagnosticStackEntry(derived d, bool w)
+ : derived(d)
+ , Weak(w)
+ {
+ }
+ bool Weak;
+};
+
struct cmStateDetail::BuildsystemDirectoryStateType
{
cmStateDetail::PositionType CurrentScope;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 50fc8d1..e568177 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -4,6 +4,7 @@
#include "cmStateSnapshot.h"
#include <algorithm>
+#include <array>
#include <cassert>
#include <set>
#include <string>
@@ -168,7 +169,7 @@
return true;
}
-bool cmStateSnapshot::CanPopPolicyScope()
+bool cmStateSnapshot::CanPopPolicyScope() const
{
return this->Position->Policies != this->Position->PolicyScope;
}
@@ -224,6 +225,129 @@
return status;
}
+void cmStateSnapshot::PushDiagnostic(cmDiagnostics::DiagnosticMap entry,
+ bool weak)
+{
+ cmStateDetail::PositionType pos = this->Position;
+ pos->Diagnostics = this->State->DiagnosticStack.Push(
+ pos->Diagnostics, cmStateDetail::DiagnosticStackEntry(entry, weak));
+}
+
+bool cmStateSnapshot::PopDiagnostic()
+{
+ cmStateDetail::PositionType pos = this->Position;
+ if (pos->Diagnostics == pos->DiagnosticScope) {
+ return false;
+ }
+ pos->Diagnostics = this->State->DiagnosticStack.Pop(pos->Diagnostics);
+ return true;
+}
+
+bool cmStateSnapshot::CanPopDiagnosticScope() const
+{
+ return this->Position->Diagnostics != this->Position->DiagnosticScope;
+}
+
+void cmStateSnapshot::SetDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive)
+{
+ assert(action != cmDiagnostics::Undefined);
+
+ auto function = [](cmDiagnosticAction, cmDiagnosticAction) -> bool {
+ return true;
+ };
+
+ this->AlterDiagnostic(category, action, function, recursive);
+}
+
+void cmStateSnapshot::PromoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action,
+ bool recursive)
+{
+ assert(action != cmDiagnostics::Undefined);
+
+ auto function = [](cmDiagnosticAction current,
+ cmDiagnosticAction desired) -> bool {
+ return (current < desired);
+ };
+
+ this->AlterDiagnostic(category, action, function, recursive);
+}
+
+void cmStateSnapshot::DemoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action,
+ bool recursive)
+{
+ assert(action != cmDiagnostics::Undefined);
+
+ auto function = [](cmDiagnosticAction current,
+ cmDiagnosticAction desired) -> bool {
+ return (current > desired);
+ };
+
+ this->AlterDiagnostic(category, action, function, recursive);
+}
+
+void cmStateSnapshot::AlterDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action,
+ AlterDiagnosticFunction function,
+ bool recursive)
+{
+ if (recursive) {
+ unsigned i = category;
+ for (;;) {
+ this->AlterDiagnostic(static_cast<cmDiagnosticCategory>(i), action,
+ function, false);
+ if (++i >= cmDiagnostics::CategoryCount) {
+ break;
+ }
+ if (cmDiagnostics::CategoryInfo[i].Parent < category) {
+ break;
+ }
+ }
+ } else {
+ cmDiagnosticAction const oldAction = this->GetDiagnostic(category);
+ if (function(oldAction, action)) {
+ // Update the policy stack from the top to the top-most strong entry.
+ bool previous_was_weak = true;
+ for (cmLinkedTree<cmStateDetail::DiagnosticStackEntry>::iterator dsi =
+ this->Position->Diagnostics;
+ previous_was_weak && dsi != this->Position->DiagnosticRoot; ++dsi) {
+ (*dsi)[category] = action;
+ previous_was_weak = dsi->Weak;
+ }
+ }
+ }
+}
+
+cmDiagnosticAction cmStateSnapshot::GetDiagnostic(
+ cmDiagnosticCategory category, cmDiagnosticAction defaultAction) const
+{
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir =
+ this->Position->BuildSystemDirectory;
+
+ while (true) {
+ assert(dir.IsValid());
+ cmLinkedTree<cmStateDetail::DiagnosticStackEntry>::iterator leaf =
+ dir->CurrentScope->Diagnostics;
+ cmLinkedTree<cmStateDetail::DiagnosticStackEntry>::iterator root =
+ dir->CurrentScope->DiagnosticRoot;
+ for (; leaf != root; ++leaf) {
+ cmDiagnosticAction const action = (*leaf)[category];
+ if (action != cmDiagnostics::Undefined) {
+ return action;
+ }
+ }
+ cmStateDetail::PositionType e = dir->CurrentScope;
+ cmStateDetail::PositionType p = e->DirectoryParent;
+ if (p == this->State->SnapshotData.Root()) {
+ break;
+ }
+ dir = p->BuildSystemDirectory;
+ }
+ return defaultAction;
+}
+
cmValue cmStateSnapshot::GetDefinition(std::string const& name) const
{
assert(this->Position->Vars.IsValid());
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index d181fad..f727123 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -10,6 +10,7 @@
#include <cm/string_view>
+#include "cmDiagnostics.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmValue.h"
@@ -55,7 +56,24 @@
bool parent_scope = false) const;
void PushPolicy(cmPolicies::PolicyMap const& entry, bool weak);
bool PopPolicy();
- bool CanPopPolicyScope();
+ bool CanPopPolicyScope() const;
+
+ void SetDiagnostic(cmDiagnosticCategory category, cmDiagnosticAction action,
+ bool recursive);
+ void PromoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive);
+ void DemoteDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action, bool recursive);
+ cmDiagnosticAction GetDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction defaultAction) const;
+ cmDiagnosticAction GetDiagnostic(cmDiagnosticCategory category) const
+ {
+ return this->GetDiagnostic(
+ category, cmDiagnostics::CategoryInfo[category].DefaultAction);
+ }
+ void PushDiagnostic(cmDiagnostics::DiagnosticMap entry, bool weak);
+ bool PopDiagnostic();
+ bool CanPopDiagnosticScope() const;
cmState* GetState() const;
@@ -89,6 +107,12 @@
void InitializeFromParent();
+ using AlterDiagnosticFunction = bool (*)(cmDiagnosticAction current,
+ cmDiagnosticAction desired);
+ void AlterDiagnostic(cmDiagnosticCategory category,
+ cmDiagnosticAction action,
+ AlterDiagnosticFunction function, bool recursive);
+
cmState* State;
cmStateDetail::PositionType Position;
};
diff --git a/Source/cmStdIoInit.cxx b/Source/cmStdIoInit.cxx
index 0d7a3d0..e6e2e16 100644
--- a/Source/cmStdIoInit.cxx
+++ b/Source/cmStdIoInit.cxx
@@ -17,6 +17,9 @@
# include "cm_fileno.hxx"
#else
+# include <cm/string_view>
+# include <cmext/string_view>
+
# include <unistd.h>
#endif
@@ -118,6 +121,17 @@
#else
// On non-Windows platforms, we select the user's locale.
std::setlocale(LC_CTYPE, "");
+
+ // In the "C" locale try switching to a UTF-8 character set.
+ if (char const* locale = std::setlocale(LC_CTYPE, nullptr)) {
+ if (locale == "C"_s || locale == "POSIX"_s) {
+ std::setlocale(LC_CTYPE, "C.UTF-8")
+# ifdef __APPLE__
+ || std::setlocale(LC_CTYPE, "UTF-8")
+# endif
+ || std::setlocale(LC_CTYPE, "en_US.UTF-8");
+ }
+ }
#endif
}
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c0049ba..8ec4cb0 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -847,10 +847,12 @@
std::string* captureStdOut,
std::string* captureStdErr, int* retVal,
char const* dir, OutputOption outputflag,
- cmDuration timeout, Encoding encoding)
+ cmDuration timeout, Encoding encoding,
+ std::vector<std::string> env)
{
cmUVProcessChainBuilder builder;
builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, stdin)
+ .SetEnvironment(std::move(env))
.AddCommand(command);
if (dir) {
builder.SetWorkingDirectory(dir);
@@ -1770,9 +1772,9 @@
unsigned int i;
numf = d.GetNumberOfFiles();
for (i = 0; i < numf; i++) {
- std::string fname = d.GetFile(i);
+ std::string const& fname = d.GetFileName(i);
if (reg.find(fname)) {
- files.push_back(std::move(fname));
+ files.push_back(fname);
}
}
}
@@ -1792,9 +1794,9 @@
cmsys::Directory d;
if (d.Load(startPath)) {
for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
- if ((std::string(d.GetFile(i)) != ".") &&
- (std::string(d.GetFile(i)) != "..")) {
- std::string fname = cmStrCat(startPath, '/', d.GetFile(i));
+ std::string const& f = d.GetFileName(i);
+ if (f != "." && f != "..") {
+ std::string fname = cmStrCat(startPath, '/', f);
if (cmSystemTools::FileIsDirectory(fname)) {
fname += finishPath;
cmSystemTools::GlobDirs(fname, files);
@@ -1823,14 +1825,13 @@
cmsys::Directory d;
if (d.Load(path)) {
for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
- if ((std::string(d.GetFile(i)) != ".") &&
- (std::string(d.GetFile(i)) != "..")) {
+ std::string const& sfname = d.GetFileName(i);
+ if (sfname != "." && sfname != "..") {
std::string fname = path;
if (path.back() != '/') {
fname += "/";
}
- fname += d.GetFile(i);
- std::string sfname = d.GetFile(i);
+ fname += sfname;
if (type > 0 && cmSystemTools::FileIsDirectory(fname)) {
continue;
}
@@ -2100,167 +2101,30 @@
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
{
std::vector<std::string> env;
- int cc;
# ifdef _WIN32
- // if program starts with main, _wenviron is initially NULL, call to
- // _wgetenv and create wide-character string environment
- _wgetenv(L"");
- for (cc = 0; _wenviron[cc]; ++cc) {
- env.emplace_back(cmsys::Encoding::ToNarrow(_wenviron[cc]));
+ struct EnvDeleter
+ {
+ void operator()(wchar_t* p) const { FreeEnvironmentStringsW(p); }
+ };
+
+ auto block = std::unique_ptr<wchar_t, EnvDeleter>(GetEnvironmentStringsW());
+ if (!block) {
+ return env;
+ }
+
+ for (wchar_t const* p = block.get(); *p; p += wcslen(p) + 1) {
+ if (p[0] != L'=') {
+ env.emplace_back(cmsys::Encoding::ToNarrow(p));
+ }
}
# else
- for (cc = 0; environ[cc]; ++cc) {
+ for (int cc = 0; environ[cc]; ++cc) {
env.emplace_back(environ[cc]);
}
# endif
return env;
}
-void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
-{
- for (std::string const& var : env) {
- cmSystemTools::PutEnv(var);
- }
-}
-
-void cmSystemTools::EnvDiff::AppendEnv(std::vector<std::string> const& env)
-{
- for (std::string const& var : env) {
- this->PutEnv(var);
- }
-}
-
-void cmSystemTools::EnvDiff::PutEnv(std::string const& env)
-{
- auto const eq_loc = env.find('=');
- if (eq_loc != std::string::npos) {
- std::string name = env.substr(0, eq_loc);
- diff[name] = env.substr(eq_loc + 1);
- } else {
- this->UnPutEnv(env);
- }
-}
-
-void cmSystemTools::EnvDiff::UnPutEnv(std::string const& env)
-{
- diff[env] = cm::nullopt;
-}
-
-bool cmSystemTools::EnvDiff::ParseOperation(std::string const& envmod)
-{
- char path_sep = GetSystemPathlistSeparator();
-
- auto apply_diff = [this](std::string const& name,
- std::function<void(std::string&)> const& apply) {
- cm::optional<std::string> old_value = diff[name];
- std::string output;
- if (old_value) {
- output = *old_value;
- } else {
- char const* curval = cmSystemTools::GetEnv(name);
- if (curval) {
- output = curval;
- }
- }
- apply(output);
- diff[name] = output;
- };
-
- // Split on `=`
- auto const eq_loc = envmod.find_first_of('=');
- if (eq_loc == std::string::npos) {
- cmSystemTools::Error(cmStrCat(
- "Error: Missing `=` after the variable name in: ", envmod, '\n'));
- return false;
- }
-
- auto const name = envmod.substr(0, eq_loc);
-
- // Split value on `:`
- auto const op_value_start = eq_loc + 1;
- auto const colon_loc = envmod.find_first_of(':', op_value_start);
- if (colon_loc == std::string::npos) {
- cmSystemTools::Error(
- cmStrCat("Error: Missing `:` after the operation in: ", envmod, '\n'));
- return false;
- }
- auto const op = envmod.substr(op_value_start, colon_loc - op_value_start);
-
- auto const value_start = colon_loc + 1;
- auto const value = envmod.substr(value_start);
-
- // Determine what to do with the operation.
- if (op == "reset"_s) {
- auto entry = diff.find(name);
- if (entry != diff.end()) {
- diff.erase(entry);
- }
- } else if (op == "set"_s) {
- diff[name] = value;
- } else if (op == "unset"_s) {
- diff[name] = cm::nullopt;
- } else if (op == "string_append"_s) {
- apply_diff(name, [&value](std::string& output) { output += value; });
- } else if (op == "string_prepend"_s) {
- apply_diff(name,
- [&value](std::string& output) { output.insert(0, value); });
- } else if (op == "path_list_append"_s) {
- apply_diff(name, [&value, path_sep](std::string& output) {
- if (!output.empty()) {
- output += path_sep;
- }
- output += value;
- });
- } else if (op == "path_list_prepend"_s) {
- apply_diff(name, [&value, path_sep](std::string& output) {
- if (!output.empty()) {
- output.insert(output.begin(), path_sep);
- }
- output.insert(0, value);
- });
- } else if (op == "cmake_list_append"_s) {
- apply_diff(name, [&value](std::string& output) {
- if (!output.empty()) {
- output += ';';
- }
- output += value;
- });
- } else if (op == "cmake_list_prepend"_s) {
- apply_diff(name, [&value](std::string& output) {
- if (!output.empty()) {
- output.insert(output.begin(), ';');
- }
- output.insert(0, value);
- });
- } else {
- cmSystemTools::Error(cmStrCat(
- "Error: Unrecognized environment manipulation argument: ", op, '\n'));
- return false;
- }
-
- return true;
-}
-
-void cmSystemTools::EnvDiff::ApplyToCurrentEnv(std::ostringstream* measurement)
-{
- for (auto const& env_apply : diff) {
- if (env_apply.second) {
- auto const env_update =
- cmStrCat(env_apply.first, '=', *env_apply.second);
- cmSystemTools::PutEnv(env_update);
- if (measurement) {
- *measurement << env_update << std::endl;
- }
- } else {
- cmSystemTools::UnsetEnv(env_apply.first.c_str());
- if (measurement) {
- // Signify that this variable is being actively unset
- *measurement << '#' << env_apply.first << "=\n";
- }
- }
- }
-}
-
cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
{
this->Env = cmSystemTools::GetEnvironmentVariables();
@@ -2280,7 +2144,9 @@
}
// Then put back each entry from the original environment:
- cmSystemTools::AppendEnv(this->Env);
+ for (std::string const& var : this->Env) {
+ cmSystemTools::PutEnv(var);
+ }
}
#endif
@@ -2359,13 +2225,11 @@
cmHasLiteralSuffix(path, ".dylib"));
}
-bool cmSystemTools::CreateTar(std::string const& arFileName,
- std::vector<std::string> const& files,
- std::string const& workingDirectory,
- cmTarCompression compressType, bool verbose,
- std::string const& mtime,
- std::string const& format, int compressionLevel,
- int numThreads)
+bool cmSystemTools::CreateTar(
+ std::string const& arFileName, std::vector<std::string> const& files,
+ std::string const& workingDirectory, cmTarCompression compressType,
+ std::string const& encoding, bool verbose, std::string const& mtime,
+ std::string const& format, int compressionLevel, int numThreads)
{
#if !defined(CMAKE_BOOTSTRAP)
cmWorkingDirectory workdir(cmSystemTools::GetLogicalWorkingDirectory());
@@ -2416,7 +2280,7 @@
break;
}
- cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format,
+ cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format, encoding,
compressionLevel, numThreads);
if (!a.Open()) {
@@ -2440,6 +2304,7 @@
#else
(void)arFileName;
(void)files;
+ (void)encoding;
(void)verbose;
return false;
#endif
@@ -2619,7 +2484,8 @@
}
bool extract_tar(std::string const& arFileName,
- std::vector<std::string> const& files, bool verbose,
+ std::vector<std::string> const& files,
+ std::string const& encoding, bool verbose,
cmSystemTools::cmTarExtractTimestamps extractTimestamps,
bool extract)
{
@@ -2640,6 +2506,15 @@
}
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
+
+ if (encoding != "OEM") {
+ if (archive_read_set_options(
+ a, cmStrCat("hdrcharset=", encoding).c_str()) != ARCHIVE_OK) {
+ cmSystemTools::Error(
+ cmStrCat("Cannot set archive encoding: ", encoding));
+ return false;
+ }
+ }
struct archive_entry* entry;
struct archive* matching = archive_match_new();
@@ -2749,14 +2624,16 @@
bool cmSystemTools::ExtractTar(std::string const& arFileName,
std::vector<std::string> const& files,
cmTarExtractTimestamps extractTimestamps,
- bool verbose)
+ std::string const& encoding, bool verbose)
{
#if !defined(CMAKE_BOOTSTRAP)
- return extract_tar(arFileName, files, verbose, extractTimestamps, true);
+ return extract_tar(arFileName, files, encoding, verbose, extractTimestamps,
+ true);
#else
(void)arFileName;
(void)files;
(void)extractTimestamps;
+ (void)encoding;
(void)verbose;
return false;
#endif
@@ -2764,14 +2641,15 @@
bool cmSystemTools::ListTar(std::string const& arFileName,
std::vector<std::string> const& files,
- bool verbose)
+ std::string const& encoding, bool verbose)
{
#if !defined(CMAKE_BOOTSTRAP)
- return extract_tar(arFileName, files, verbose, cmTarExtractTimestamps::Yes,
- false);
+ return extract_tar(arFileName, files, encoding, verbose,
+ cmTarExtractTimestamps::Yes, false);
#else
(void)arFileName;
(void)files;
+ (void)encoding;
(void)verbose;
return false;
#endif
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index c28a0b2..7eaee0e 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -10,8 +10,6 @@
#include <cstddef>
#include <functional>
-#include <map>
-#include <sstream>
#include <string>
#include <vector>
@@ -293,7 +291,8 @@
char const* dir = nullptr,
OutputOption outputflag = OUTPUT_MERGE,
cmDuration timeout = cmDuration::zero(),
- Encoding encoding = cmProcessOutput::Auto);
+ Encoding encoding = cmProcessOutput::Auto,
+ std::vector<std::string> env = {});
static std::string PrintSingleCommand(std::vector<std::string> const&);
@@ -450,45 +449,6 @@
/** Get the list of all environment variables */
static std::vector<std::string> GetEnvironmentVariables();
- /** Append multiple variables to the current environment. */
- static void AppendEnv(std::vector<std::string> const& env);
-
- /**
- * Helper class to represent an environment diff directly. This is to avoid
- * repeated in-place environment modification (i.e. via setenv/putenv), which
- * could be slow.
- */
- class EnvDiff
- {
- public:
- /** Append multiple variables to the current environment diff */
- void AppendEnv(std::vector<std::string> const& env);
-
- /**
- * Add a single variable (or remove if no = sign) to the current
- * environment diff.
- */
- void PutEnv(std::string const& env);
-
- /** Remove a single variable from the current environment diff. */
- void UnPutEnv(std::string const& env);
-
- /**
- * Apply an ENVIRONMENT_MODIFICATION operation to this diff. Returns
- * false and issues an error on parse failure.
- */
- bool ParseOperation(std::string const& envmod);
-
- /**
- * Apply this diff to the actual environment, optionally writing out the
- * modifications to a CTest-compatible measurement stream.
- */
- void ApplyToCurrentEnv(std::ostringstream* measurement = nullptr);
-
- private:
- std::map<std::string, cm::optional<std::string>> diff;
- };
-
/** Helper class to save and restore the environment.
Instantiate this class as an automatic variable on
the stack. Its constructor saves a copy of the current
@@ -562,18 +522,20 @@
};
static bool ListTar(std::string const& arFileName,
- std::vector<std::string> const& files, bool verbose);
+ std::vector<std::string> const& files,
+ std::string const& encoding, bool verbose);
static bool CreateTar(std::string const& arFileName,
std::vector<std::string> const& files,
std::string const& workingDirectory,
- cmTarCompression compressType, bool verbose,
+ cmTarCompression compressType,
+ std::string const& encoding, bool verbose,
std::string const& mtime = std::string(),
std::string const& format = std::string(),
int compressionLevel = 0, int numThreads = 1);
static bool ExtractTar(std::string const& arFileName,
std::vector<std::string> const& files,
cmTarExtractTimestamps extractTimestamps,
- bool verbose);
+ std::string const& encoding, bool verbose);
/** Random number generation. */
static unsigned int RandomSeed();
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 296adf5..4d46bf4 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -4,6 +4,7 @@
#include <algorithm>
#include <cassert>
+#include <functional>
#include <iterator>
#include <map>
#include <set>
@@ -21,6 +22,7 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmFindPackageStack.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
@@ -98,18 +100,18 @@
namespace {
struct FileSetEntries
{
- FileSetEntries(cm::static_string_view propertyName)
+ FileSetEntries(cm::string_view propertyName)
: PropertyName(propertyName)
{
}
- cm::static_string_view const PropertyName;
+ cm::string_view const PropertyName;
std::vector<BT<std::string>> Entries;
};
struct FileSetType
{
- FileSetType(cm::static_string_view typeName,
+ FileSetType(cm::string_view typeName,
cm::static_string_view defaultDirectoryProperty,
cm::static_string_view defaultPathProperty,
cm::static_string_view directoryPrefix,
@@ -131,7 +133,7 @@
{
}
- cm::static_string_view const TypeName;
+ cm::string_view const TypeName;
cm::static_string_view const DefaultDirectoryProperty;
cm::static_string_view const DefaultPathProperty;
cm::static_string_view const DirectoryPrefix;
@@ -157,7 +159,7 @@
cmTargetInternals const* impl,
std::string const& prop) const;
- void AddFileSet(std::string const& name, cmFileSetVisibility vis,
+ void AddFileSet(std::string const& name, cm::FileSetMetadata::Visibility vis,
cmListFileBacktrace bt);
};
@@ -378,6 +380,9 @@
{ "Swift_LANGUAGE_VERSION"_s, IC::CanCompileSources },
{ "Swift_MODULE_DIRECTORY"_s, IC::CanCompileSources },
{ "Swift_COMPILATION_MODE"_s, IC::CanCompileSources },
+ // ---- Rust
+ { "Rust_EDITION"_s, IC::CanCompileSources },
+ { "Rust_MAIN_CRATE_ROOT"_s, IC::CanCompileSources },
// ---- moc
{ "AUTOMOC"_s, IC::CanCompileSources },
{ "AUTOMOC_COMPILER_PREDEFINES"_s, IC::CanCompileSources },
@@ -649,8 +654,7 @@
UsageRequirementProperty ImportedCxxModulesCompileOptions;
UsageRequirementProperty ImportedCxxModulesLinkLibraries;
- FileSetType HeadersFileSets;
- FileSetType CxxModulesFileSets;
+ std::unordered_map<cm::string_view, FileSetType> FileSetTypes;
cmTargetInternals();
@@ -704,17 +708,25 @@
"IMPORTED_CXX_MODULES_COMPILE_FEATURES"_s)
, ImportedCxxModulesCompileOptions("IMPORTED_CXX_MODULES_COMPILE_OPTIONS"_s)
, ImportedCxxModulesLinkLibraries("IMPORTED_CXX_MODULES_LINK_LIBRARIES"_s)
- , HeadersFileSets("HEADERS"_s, "HEADER_DIRS"_s, "HEADER_SET"_s,
- "HEADER_DIRS_"_s, "HEADER_SET_"_s, "Header"_s,
- "The default header set"_s, "Header set"_s,
- FileSetEntries("HEADER_SETS"_s),
- FileSetEntries("INTERFACE_HEADER_SETS"_s))
- , CxxModulesFileSets("CXX_MODULES"_s, "CXX_MODULE_DIRS"_s,
- "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
- "CXX_MODULE_SET_"_s, "C++ module"_s,
- "The default C++ module set"_s, "C++ module set"_s,
- FileSetEntries("CXX_MODULE_SETS"_s),
- FileSetEntries("INTERFACE_CXX_MODULE_SETS"_s))
+ , FileSetTypes{ { cm::FileSetMetadata::HEADERS,
+ { cm::FileSetMetadata::HEADERS, "HEADER_DIRS"_s,
+ "HEADER_SET"_s, "HEADER_DIRS_"_s, "HEADER_SET_"_s,
+ "Header"_s, "The default header set"_s, "Header set"_s,
+ FileSetEntries{ "HEADER_SETS"_s },
+ FileSetEntries{ "INTERFACE_HEADER_SETS"_s } } },
+ { cm::FileSetMetadata::SOURCES,
+ { cm::FileSetMetadata::SOURCES, "SOURCE_DIRS"_s,
+ "SOURCE_SET"_s, "SOURCE_DIRS_"_s, "SOURCE_SET_"_s,
+ "Source"_s, "The default source set"_s, "Source set"_s,
+ FileSetEntries{ "SOURCE_SETS"_s },
+ FileSetEntries{ "INTERFACE_SOURCE_SETS"_s } } },
+ { cm::FileSetMetadata::CXX_MODULES,
+ { cm::FileSetMetadata::CXX_MODULES, "CXX_MODULE_DIRS"_s,
+ "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
+ "CXX_MODULE_SET_"_s, "C++ module"_s,
+ "The default C++ module set"_s, "C++ module set"_s,
+ FileSetEntries{ "CXX_MODULE_SETS"_s },
+ FileSetEntries{ "INTERFACE_CXX_MODULE_SETS"_s } } } }
{
}
@@ -803,13 +815,14 @@
return { did_read, value };
}
-void FileSetType::AddFileSet(std::string const& name, cmFileSetVisibility vis,
+void FileSetType::AddFileSet(std::string const& name,
+ cm::FileSetMetadata::Visibility vis,
cmListFileBacktrace bt)
{
- if (cmFileSetVisibilityIsForSelf(vis)) {
+ if (cm::FileSetMetadata::VisibilityIsForSelf(vis)) {
this->SelfEntries.Entries.emplace_back(name, bt);
}
- if (cmFileSetVisibilityIsForInterface(vis)) {
+ if (cm::FileSetMetadata::VisibilityIsForInterface(vis)) {
this->InterfaceEntries.Entries.emplace_back(name, std::move(bt));
}
}
@@ -1721,53 +1734,70 @@
assert(!this->IsNormal());
// Imported targets cannot be the target of a copy.
assert(!this->IsImported());
- // Only imported targets can be the source of a copy.
- assert(tgt->IsImported());
+
+ // Only imported or normal targets can be the source of a copy.
+ assert(tgt->IsImported() || tgt->IsNormal());
this->impl->PolicyMap = tgt->impl->PolicyMap;
this->impl->TemplateTarget = tgt;
}
-void cmTarget::CopyImportedCxxModulesEntries(cmTarget const* tgt)
+void cmTarget::CopyCxxModulesEntries(cmTarget const* tgt)
{
// Normal targets cannot be the target of a copy.
assert(!this->IsNormal());
// Imported targets cannot be the target of a copy.
assert(!this->IsImported());
- // Only imported targets can be the source of a copy.
- assert(tgt->IsImported());
+ // Only imported or normal targets can be the source of a copy.
+ assert(tgt->IsImported() || tgt->IsNormal());
this->impl->IncludeDirectories.Entries.clear();
- this->impl->IncludeDirectories.CopyFromEntries(
- cmMakeRange(tgt->impl->ImportedCxxModulesIncludeDirectories.Entries));
this->impl->CompileDefinitions.Entries.clear();
- this->impl->CompileDefinitions.CopyFromEntries(
- cmMakeRange(tgt->impl->ImportedCxxModulesCompileDefinitions.Entries));
this->impl->CompileFeatures.Entries.clear();
- this->impl->CompileFeatures.CopyFromEntries(
- cmMakeRange(tgt->impl->ImportedCxxModulesCompileFeatures.Entries));
this->impl->CompileOptions.Entries.clear();
- this->impl->CompileOptions.CopyFromEntries(
- cmMakeRange(tgt->impl->ImportedCxxModulesCompileOptions.Entries));
this->impl->LinkLibraries.Entries.clear();
- this->impl->LinkLibraries.CopyFromEntries(
- cmMakeRange(tgt->impl->ImportedCxxModulesLinkLibraries.Entries));
+
+ if (tgt->IsImported()) {
+ this->impl->IncludeDirectories.CopyFromEntries(
+ cmMakeRange(tgt->impl->ImportedCxxModulesIncludeDirectories.Entries));
+ this->impl->CompileDefinitions.CopyFromEntries(
+ cmMakeRange(tgt->impl->ImportedCxxModulesCompileDefinitions.Entries));
+ this->impl->CompileFeatures.CopyFromEntries(
+ cmMakeRange(tgt->impl->ImportedCxxModulesCompileFeatures.Entries));
+ this->impl->CompileOptions.CopyFromEntries(
+ cmMakeRange(tgt->impl->ImportedCxxModulesCompileOptions.Entries));
+ this->impl->LinkLibraries.CopyFromEntries(
+ cmMakeRange(tgt->impl->ImportedCxxModulesLinkLibraries.Entries));
+ } else {
+ this->impl->IncludeDirectories.CopyFromEntries(
+ cmMakeRange(tgt->impl->IncludeDirectories.Entries));
+ this->impl->CompileDefinitions.CopyFromEntries(
+ cmMakeRange(tgt->impl->CompileDefinitions.Entries));
+ this->impl->CompileFeatures.CopyFromEntries(
+ cmMakeRange(tgt->impl->CompileFeatures.Entries));
+ this->impl->CompileOptions.CopyFromEntries(
+ cmMakeRange(tgt->impl->CompileOptions.Entries));
+ this->impl->LinkLibraries.CopyFromEntries(
+ cmMakeRange(tgt->impl->LinkLibraries.Entries));
+ }
// Copy the C++ module fileset entries from `tgt`'s `INTERFACE` to this
// target's `PRIVATE`.
- this->impl->CxxModulesFileSets.SelfEntries.Entries.clear();
- this->impl->CxxModulesFileSets.SelfEntries.Entries =
- tgt->impl->CxxModulesFileSets.InterfaceEntries.Entries;
+ auto& entries = this->impl->FileSetTypes.at(cm::FileSetMetadata::CXX_MODULES)
+ .SelfEntries.Entries;
+ entries.clear();
+ entries = tgt->impl->FileSetTypes.at(cm::FileSetMetadata::CXX_MODULES)
+ .InterfaceEntries.Entries;
}
-void cmTarget::CopyImportedCxxModulesProperties(cmTarget const* tgt)
+void cmTarget::CopyCxxModulesProperties(cmTarget const* tgt)
{
// Normal targets cannot be the target of a copy.
assert(!this->IsNormal());
// Imported targets cannot be the target of a copy.
assert(!this->IsImported());
- // Only imported targets can be the source of a copy.
- assert(tgt->IsImported());
+ // Only imported or normal targets can be the source of a copy.
+ assert(tgt->IsImported() || tgt->IsNormal());
// The list of properties that are relevant here include:
// - compilation-specific properties for any language or platform
@@ -1905,24 +1935,26 @@
}
}
-cmBTStringRange cmTarget::GetHeaderSetsEntries() const
-{
- return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries);
+namespace {
+std::vector<BT<std::string>> EmptyEntries;
}
-cmBTStringRange cmTarget::GetCxxModuleSetsEntries() const
+cmBTStringRange cmTarget::GetFileSetsEntries(cm::string_view type) const
{
- return cmMakeRange(this->impl->CxxModulesFileSets.SelfEntries.Entries);
+ if (cm::contains(this->impl->FileSetTypes, type)) {
+ return cmMakeRange(this->impl->FileSetTypes.at(type).SelfEntries.Entries);
+ }
+ return cmMakeRange(EmptyEntries);
}
-cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const
+cmBTStringRange cmTarget::GetInterfaceFileSetsEntries(
+ cm::string_view type) const
{
- return cmMakeRange(this->impl->HeadersFileSets.InterfaceEntries.Entries);
-}
-
-cmBTStringRange cmTarget::GetInterfaceCxxModuleSetsEntries() const
-{
- return cmMakeRange(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
+ if (cm::contains(this->impl->FileSetTypes, type)) {
+ return cmMakeRange(
+ this->impl->FileSetTypes.at(type).InterfaceEntries.Entries);
+ }
+ return cmMakeRange(EmptyEntries);
}
namespace {
@@ -2116,14 +2148,9 @@
}
}
- FileSetType* fileSetTypes[] = {
- &this->impl->HeadersFileSets,
- &this->impl->CxxModulesFileSets,
- };
-
- for (auto* fileSetType : fileSetTypes) {
- if (fileSetType->WriteProperties(this, this->impl.get(), prop, value,
- FileSetType::Action::Set)) {
+ for (auto& fileSetType : this->impl->FileSetTypes) {
+ if (fileSetType.second.WriteProperties(this, this->impl.get(), prop, value,
+ FileSetType::Action::Set)) {
return;
}
}
@@ -2236,14 +2263,9 @@
}
}
- FileSetType* fileSetTypes[] = {
- &this->impl->HeadersFileSets,
- &this->impl->CxxModulesFileSets,
- };
-
- for (auto* fileSetType : fileSetTypes) {
- if (fileSetType->WriteProperties(this, this->impl.get(), prop, value,
- FileSetType::Action::Append)) {
+ for (auto& fileSetType : this->impl->FileSetTypes) {
+ if (fileSetType.second.WriteProperties(this, this->impl.get(), prop, value,
+ FileSetType::Action::Append)) {
return;
}
}
@@ -2719,13 +2741,9 @@
// Check fileset properties.
{
- FileSetType* fileSetTypes[] = {
- &this->impl->HeadersFileSets,
- &this->impl->CxxModulesFileSets,
- };
-
- for (auto* fileSetType : fileSetTypes) {
- auto value = fileSetType->ReadProperties(this, this->impl.get(), prop);
+ for (auto const& fileSetType : this->impl->FileSetTypes) {
+ auto value =
+ fileSetType.second.ReadProperties(this, this->impl.get(), prop);
if (value.first) {
return value.second;
}
@@ -3148,39 +3166,37 @@
}
std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
- std::string const& name, std::string const& type, cmFileSetVisibility vis)
+ std::string const& name, std::string const& type,
+ cm::FileSetMetadata::Visibility vis)
{
auto result = this->impl->FileSets.emplace(
- name, cmFileSet(this->GetMakefile(), name, type, vis));
+ name, cmFileSet(this->GetMakefile(), this, name, type, vis));
if (result.second) {
auto bt = this->impl->Makefile->GetBacktrace();
- if (type == this->impl->HeadersFileSets.TypeName) {
- this->impl->HeadersFileSets.AddFileSet(name, vis, std::move(bt));
- } else if (type == this->impl->CxxModulesFileSets.TypeName) {
- this->impl->CxxModulesFileSets.AddFileSet(name, vis, std::move(bt));
+ if (cm::contains(this->impl->FileSetTypes, type)) {
+ this->impl->FileSetTypes.at(type).AddFileSet(name, vis, std::move(bt));
}
}
return std::make_pair(&result.first->second, result.second);
}
-std::string cmTarget::GetFileSetsPropertyName(std::string const& type)
+std::string cmTarget::GetFileSetsPropertyName(std::string const& type) const
{
- if (type == "HEADERS") {
- return "HEADER_SETS";
- }
- if (type == "CXX_MODULES") {
- return "CXX_MODULE_SETS";
+ if (cm::contains(this->impl->FileSetTypes, type)) {
+ return std::string{
+ this->impl->FileSetTypes.at(type).SelfEntries.PropertyName
+ };
}
return "";
}
-std::string cmTarget::GetInterfaceFileSetsPropertyName(std::string const& type)
+std::string cmTarget::GetInterfaceFileSetsPropertyName(
+ std::string const& type) const
{
- if (type == "HEADERS") {
- return "INTERFACE_HEADER_SETS";
- }
- if (type == "CXX_MODULES") {
- return "INTERFACE_CXX_MODULE_SETS";
+ if (cm::contains(this->impl->FileSetTypes, type)) {
+ return std::string{
+ this->impl->FileSetTypes.at(type).InterfaceEntries.PropertyName
+ };
}
return "";
}
@@ -3196,7 +3212,12 @@
return result;
}
-std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
+namespace {
+std::vector<std::string> RetrieveFileSetNames(
+ std::unordered_map<cm::string_view, FileSetType> const& fileSetTypes,
+ std::function<
+ std::vector<BT<std::string>> const&(FileSetType const& fileSetType)>
+ GetFileSets)
{
std::vector<std::string> result;
auto inserter = std::back_inserter(result);
@@ -3208,11 +3229,31 @@
}
};
- appendEntries(this->impl->HeadersFileSets.InterfaceEntries.Entries);
- appendEntries(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
+ for (auto const& fileSetType : fileSetTypes) {
+ appendEntries(GetFileSets(fileSetType.second));
+ }
return result;
}
+}
+
+std::vector<std::string> cmTarget::GetAllPrivateFileSets() const
+{
+ return RetrieveFileSetNames(
+ this->impl->FileSetTypes,
+ [](FileSetType const& fileSetType) -> std::vector<BT<std::string>> const& {
+ return fileSetType.SelfEntries.Entries;
+ });
+}
+
+std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
+{
+ return RetrieveFileSetNames(
+ this->impl->FileSetTypes,
+ [](FileSetType const& fileSetType) -> std::vector<BT<std::string>> const& {
+ return fileSetType.InterfaceEntries.Entries;
+ });
+}
bool cmTarget::HasFileSets() const
{
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index b275e47..c59afb3 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -13,6 +13,7 @@
#include <vector>
#include <cm/optional>
+#include <cm/string_view>
#include "cmAlgorithms.h"
#include "cmListFileCache.h"
@@ -22,6 +23,12 @@
#include "cmTargetLinkLibraryType.h"
#include "cmValue.h"
+namespace cm {
+namespace FileSetMetadata {
+enum class Visibility;
+}
+}
+
class cmCustomCommand;
class cmFileSet;
class cmFindPackageStack;
@@ -33,8 +40,6 @@
class cmTargetExport;
class cmTargetInternals;
-enum class cmFileSetVisibility;
-
/** \class cmTarget
* \brief Represent a library or executable target loaded from a makefile.
*
@@ -321,14 +326,12 @@
cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
void CopyPolicyStatuses(cmTarget const* tgt);
- void CopyImportedCxxModulesEntries(cmTarget const* tgt);
- void CopyImportedCxxModulesProperties(cmTarget const* tgt);
+ void CopyCxxModulesEntries(cmTarget const* tgt);
+ void CopyCxxModulesProperties(cmTarget const* tgt);
- cmBTStringRange GetHeaderSetsEntries() const;
- cmBTStringRange GetCxxModuleSetsEntries() const;
+ cmBTStringRange GetFileSetsEntries(cm::string_view type) const;
- cmBTStringRange GetInterfaceHeaderSetsEntries() const;
- cmBTStringRange GetInterfaceCxxModuleSetsEntries() const;
+ cmBTStringRange GetInterfaceFileSetsEntries(cm::string_view type) const;
enum class ImportArtifactMissingOk
{
@@ -347,15 +350,16 @@
cmFileSet const* GetFileSet(std::string const& name) const;
cmFileSet* GetFileSet(std::string const& name);
- std::pair<cmFileSet*, bool> GetOrCreateFileSet(std::string const& name,
- std::string const& type,
- cmFileSetVisibility vis);
+ std::pair<cmFileSet*, bool> GetOrCreateFileSet(
+ std::string const& name, std::string const& type,
+ cm::FileSetMetadata::Visibility vis);
std::vector<std::string> GetAllFileSetNames() const;
+ std::vector<std::string> GetAllPrivateFileSets() const;
std::vector<std::string> GetAllInterfaceFileSets() const;
- static std::string GetFileSetsPropertyName(std::string const& type);
- static std::string GetInterfaceFileSetsPropertyName(std::string const& type);
+ std::string GetFileSetsPropertyName(std::string const& type) const;
+ std::string GetInterfaceFileSetsPropertyName(std::string const& type) const;
bool HasFileSets() const;
diff --git a/Source/cmTargetPropertyEntry.cxx b/Source/cmTargetPropertyEntry.cxx
new file mode 100644
index 0000000..86c2dd2
--- /dev/null
+++ b/Source/cmTargetPropertyEntry.cxx
@@ -0,0 +1,109 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+
+#include "cmTargetPropertyEntry.h"
+
+#include <string>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmGeneratorExpression.h"
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
+
+class cmake;
+
+namespace cm {
+cmLinkItem TargetPropertyEntry::NoLinkItem;
+
+class TargetPropertyEntryString : public TargetPropertyEntry
+{
+public:
+ TargetPropertyEntryString(BT<std::string> propertyValue,
+ cmLinkItem const& item = NoLinkItem)
+ : TargetPropertyEntry(item)
+ , PropertyValue(std::move(propertyValue))
+ {
+ }
+
+ std::string const& Evaluate(cm::GenEx::Context const&,
+ cmGeneratorTarget const*,
+ cmGeneratorExpressionDAGChecker*) const override
+ {
+ return this->PropertyValue.Value;
+ }
+
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->PropertyValue.Backtrace;
+ }
+ std::string const& GetInput() const override
+ {
+ return this->PropertyValue.Value;
+ }
+
+private:
+ BT<std::string> PropertyValue;
+};
+
+class TargetPropertyEntryGenex : public TargetPropertyEntry
+{
+public:
+ TargetPropertyEntryGenex(std::unique_ptr<cmCompiledGeneratorExpression> cge,
+ cmLinkItem const& item = NoLinkItem)
+ : TargetPropertyEntry(item)
+ , ge(std::move(cge))
+ {
+ }
+
+ std::string const& Evaluate(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ return this->ge->Evaluate(context, dagChecker, headTarget);
+ }
+
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->ge->GetBacktrace();
+ }
+
+ std::string const& GetInput() const override { return this->ge->GetInput(); }
+
+ bool GetHadContextSensitiveCondition() const override
+ {
+ return this->ge->GetHadContextSensitiveCondition();
+ }
+
+private:
+ std::unique_ptr<cmCompiledGeneratorExpression> const ge;
+};
+
+std::unique_ptr<TargetPropertyEntry> TargetPropertyEntry::Create(
+ cmake& cmakeInstance, const BT<std::string>& propertyValue,
+ bool evaluateForBuildsystem)
+{
+ if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) {
+ cmGeneratorExpression ge(cmakeInstance, propertyValue.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(propertyValue.Value);
+ cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
+ return std::unique_ptr<TargetPropertyEntry>(
+ cm::make_unique<TargetPropertyEntryGenex>(std::move(cge)));
+ }
+
+ return std::unique_ptr<TargetPropertyEntry>(
+ cm::make_unique<TargetPropertyEntryString>(propertyValue));
+}
+
+TargetPropertyEntry::TargetPropertyEntry(cmLinkItem const& item)
+ : LinkItem(item)
+{
+}
+
+bool TargetPropertyEntry::GetHadContextSensitiveCondition() const
+{
+ return false;
+}
+}
diff --git a/Source/cmTargetPropertyEntry.h b/Source/cmTargetPropertyEntry.h
new file mode 100644
index 0000000..4f39224
--- /dev/null
+++ b/Source/cmTargetPropertyEntry.h
@@ -0,0 +1,43 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "cmListFileCache.h"
+
+class cmLinkItem;
+class cmake;
+class cmGeneratorTarget;
+struct cmGeneratorExpressionDAGChecker;
+
+namespace cm {
+namespace GenEx {
+struct Context;
+}
+
+class TargetPropertyEntry
+{
+protected:
+ static cmLinkItem NoLinkItem;
+
+public:
+ TargetPropertyEntry(cmLinkItem const& item);
+ virtual ~TargetPropertyEntry() = default;
+
+ static std::unique_ptr<TargetPropertyEntry> Create(
+ cmake& cmakeInstance, const BT<std::string>& propertyValue,
+ bool evaluateForBuildsystem = false);
+
+ virtual std::string const& Evaluate(
+ cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker) const = 0;
+
+ virtual cmListFileBacktrace GetBacktrace() const = 0;
+ virtual std::string const& GetInput() const = 0;
+ virtual bool GetHadContextSensitiveCondition() const;
+
+ cmLinkItem const& LinkItem;
+};
+}
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 7032a56..1dd3197 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -12,6 +12,7 @@
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratorExpression.h"
#include "cmList.h"
#include "cmListFileCache.h"
@@ -227,61 +228,93 @@
this->SetError("FILE_SETs may not be added to custom targets");
return false;
}
- if (this->Target->IsFrameworkOnApple()) {
- this->SetError("FILE_SETs may not be added to FRAMEWORK targets");
+
+ if (!args.Type.empty() && !cm::FileSetMetadata::IsKnownType(args.Type)) {
+ this->SetError(
+ cmStrCat("File set TYPE may only be \"",
+ cmJoin(cm::FileSetMetadata::GetKnownTypes(), "\", \""), '"'));
+ return false;
+ }
+ if (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z' &&
+ !cm::FileSetMetadata::IsKnownType(args.FileSet)) {
+ this->SetError(
+ cmStrCat("FILE_SET names starting with a capital letter are reserved "
+ "for built-in file sets and may only be \"",
+ cmJoin(cm::FileSetMetadata::GetKnownTypes(), "\", \""), '"'));
+ return false;
+ }
+ if (!args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z' &&
+ args.Type != args.FileSet) {
+ this->SetError(cmStrCat("FILE_SET name starting with a capital letter "
+ "must match the TYPE name \"",
+ args.Type, '"'));
return false;
}
bool const isDefault = args.Type == args.FileSet ||
- (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z');
- std::string type = isDefault ? args.FileSet : args.Type;
+ (args.Type.empty() && cm::FileSetMetadata::IsKnownType(args.FileSet));
- cmFileSetVisibility visibility =
- cmFileSetVisibilityFromName(scope, this->Makefile);
+ if (!isDefault && !cm::FileSetMetadata::IsValidName(args.FileSet)) {
+ this->SetError("Non-default file set name must contain only letters, "
+ "numbers, and underscores, and must not start with a "
+ "capital letter or underscore");
+ return false;
+ }
+
+ std::string type = isDefault ? args.FileSet : args.Type;
+ cm::FileSetMetadata::Visibility visibility =
+ cm::FileSetMetadata::VisibilityFromName(scope, this->Makefile);
+
+ if (this->Target->IsFrameworkOnApple() &&
+ !cm::FileSetMetadata::IsFrameworkSupported(type)) {
+ this->SetError(cmStrCat(R"(FILE_SETs, of type ")", type,
+ R"(", may not be added to FRAMEWORK targets)"));
+ return false;
+ }
auto fileSet =
this->Target->GetOrCreateFileSet(args.FileSet, type, visibility);
if (fileSet.second) {
- if (!isDefault) {
- if (!cmFileSet::IsValidName(args.FileSet)) {
- this->SetError("Non-default file set name must contain only letters, "
- "numbers, and underscores, and must not start with a "
- "capital letter or underscore");
- return false;
- }
- }
if (type.empty()) {
this->SetError("Must specify a TYPE when creating file set");
return false;
}
- if (type != "HEADERS"_s && type != "CXX_MODULES"_s) {
- this->SetError(
- R"(File set TYPE may only be "HEADERS" or "CXX_MODULES")");
- return false;
- }
- if (cmFileSetVisibilityIsForSelf(visibility) &&
+ if (cm::FileSetMetadata::VisibilityIsForSelf(visibility) &&
this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
!this->Target->IsImported()) {
- if (type == "CXX_MODULES"_s) {
- this->SetError(R"(File set TYPE "CXX_MODULES" may not have "PUBLIC" )"
- R"(or "PRIVATE" visibility on INTERFACE libraries.)");
+ if (type == cm::FileSetMetadata::CXX_MODULES) {
+ this->SetError(
+ cmStrCat(R"(File set TYPE ")", cm::FileSetMetadata::CXX_MODULES,
+ R"(" may not have "PUBLIC" )"
+ R"(or "PRIVATE" scope on INTERFACE libraries.)"));
return false;
}
}
// FIXME(https://wg21.link/P3470): This condition can go
// away when interface-only module units are a thing.
- if (cmFileSetVisibilityIsForInterface(visibility) &&
- !cmFileSetVisibilityIsForSelf(visibility) &&
+ if (cm::FileSetMetadata::VisibilityIsForInterface(visibility) &&
+ !cm::FileSetMetadata::VisibilityIsForSelf(visibility) &&
!this->Target->IsImported()) {
- if (type == "CXX_MODULES"_s) {
- this->SetError(
- R"(File set TYPE "CXX_MODULES" may not have "INTERFACE" visibility)");
+ if (type == cm::FileSetMetadata::CXX_MODULES) {
+ this->SetError(cmStrCat(R"(File set TYPE ")",
+ cm::FileSetMetadata::CXX_MODULES,
+ R"(" may not have "INTERFACE" scope)"));
return false;
}
}
+ if (cm::FileSetMetadata::VisibilityIsForSelf(visibility) &&
+ this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
+ type == cm::FileSetMetadata::SOURCES) {
+ this->SetError(
+ cmStrCat(R"(File set TYPE ")", cm::FileSetMetadata::SOURCES,
+ R"(" may not have "PUBLIC" )"
+ R"(or "PRIVATE" scope on INTERFACE libraries.)"));
+ return false;
+ }
+
if (args.BaseDirs.empty()) {
args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory());
}
@@ -295,10 +328,11 @@
}
if (visibility != fileSet.first->GetVisibility()) {
- this->SetError(
- cmStrCat("Scope ", scope, " for file set \"", args.FileSet,
- "\" does not match original scope ",
- cmFileSetVisibilityToName(fileSet.first->GetVisibility())));
+ this->SetError(cmStrCat("Scope ", scope, " for file set \"",
+ args.FileSet,
+ "\" does not match original scope ",
+ cm::FileSetMetadata::VisibilityToName(
+ fileSet.first->GetVisibility())));
return false;
}
}
@@ -315,16 +349,16 @@
if (!baseDirectories.empty()) {
fileSet.first->AddDirectoryEntry(
BT<std::string>(baseDirectories, this->Makefile->GetBacktrace()));
- if (type == "HEADERS"_s) {
+ if (type == cm::FileSetMetadata::HEADERS) {
for (auto const& dir : cmList{ baseDirectories }) {
auto interfaceDirectoriesGenex =
cmStrCat("$<BUILD_INTERFACE:", dir, '>');
- if (cmFileSetVisibilityIsForSelf(visibility)) {
+ if (cm::FileSetMetadata::VisibilityIsForSelf(visibility)) {
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
interfaceDirectoriesGenex,
this->Makefile->GetBacktrace());
}
- if (cmFileSetVisibilityIsForInterface(visibility)) {
+ if (cm::FileSetMetadata::VisibilityIsForInterface(visibility)) {
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
interfaceDirectoriesGenex,
this->Makefile->GetBacktrace());
diff --git a/Source/cmTest.h b/Source/cmTest.h
index 0e62d6e..7d347a8 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -61,10 +61,10 @@
bool GetOldStyle() const { return this->OldStyle; }
void SetOldStyle(bool b) { this->OldStyle = b; }
- /** Get if CMP0158 policy is NEW */
- bool GetCMP0158IsNew() const
+ /** Get the CMP0158 policy setting */
+ cmPolicies::PolicyStatus GetCMP0158() const
{
- return this->PolicyStatusCMP0158 == cmPolicies::NEW;
+ return this->PolicyStatusCMP0158;
}
/** Get/Set the CMP0178 policy setting */
diff --git a/Source/cmTestDiscovery.h b/Source/cmTestDiscovery.h
new file mode 100644
index 0000000..a8d899e
--- /dev/null
+++ b/Source/cmTestDiscovery.h
@@ -0,0 +1,32 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmArgumentParser.h"
+
+struct cmTestDiscoveryArgs : ArgumentParser::ParseResult
+{
+ ArgumentParser::NonEmpty<std::vector<std::string>> Command;
+ ArgumentParser::NonEmpty<std::vector<std::string>> DiscoveryArgs;
+ ArgumentParser::NonEmpty<std::string> DiscoveryMatch;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> DiscoveryProperties;
+ ArgumentParser::NonEmpty<std::string> TestName;
+ ArgumentParser::NonEmpty<std::vector<std::string>> TestArgs;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> TestProperties;
+};
+
+template <typename Args>
+auto cmTestDiscoveryParser() -> cmArgumentParser<Args>
+{
+ static_assert(std::is_base_of<cmTestDiscoveryArgs, Args>::value, "");
+ return cmArgumentParser<Args>{}
+ .Bind("COMMAND"_s, &Args::Command)
+ .Bind("DISCOVERY_ARGS"_s, &Args::DiscoveryArgs)
+ .Bind("DISCOVERY_MATCH"_s, &Args::DiscoveryMatch)
+ .Bind("DISCOVERY_PROPERTIES"_s, &Args::DiscoveryProperties)
+ .Bind("TEST_NAME"_s, &Args::TestName)
+ .Bind("TEST_ARGS"_s, &Args::TestArgs)
+ .Bind("TEST_PROPERTIES"_s, &Args::TestProperties);
+}
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 83d798c..d003636 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -2,9 +2,7 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmTestGenerator.h"
-#include <algorithm>
#include <cstddef> // IWYU pragma: keep
-#include <iterator>
#include <memory>
#include <ostream>
#include <string>
@@ -18,10 +16,10 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
+#include "cmScriptGenerator.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -56,18 +54,13 @@
}
}
-std::size_t countMaxConsecutiveEqualSigns(std::string const& name)
+std::string TestName(cmTest* test)
{
- std::size_t max = 0;
- auto startIt = find(name.begin(), name.end(), '=');
- auto endIt = startIt;
- for (; startIt != name.end(); startIt = find(endIt, name.end(), '=')) {
- endIt =
- find_if_not(startIt + 1, name.end(), [](char c) { return c == '='; });
- max =
- std::max(max, static_cast<std::size_t>(std::distance(startIt, endIt)));
+ std::string name = test->GetName();
+ if (needToQuoteTestName(*test->GetMakefile(), name)) {
+ name = cmScriptGenerator::Quote(name);
}
- return max;
+ return name;
}
} // End: anonymous namespace
@@ -77,7 +70,7 @@
: cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations)
, Test(test)
{
- this->ActionsPerConfig = !test->GetOldStyle();
+ this->ActionsPerConfig = test == nullptr || !test->GetOldStyle();
this->TestGenerated = false;
this->LG = nullptr;
}
@@ -91,7 +84,7 @@
bool cmTestGenerator::TestsForConfig(std::string const& config)
{
- return this->GeneratesForConfig(config);
+ return this->Test != nullptr && this->GeneratesForConfig(config);
}
cmTest* cmTestGenerator::GetTest() const
@@ -99,12 +92,6 @@
return this->Test;
}
-void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
-{
- // Create the tests.
- this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
-}
-
void cmTestGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
{
if (this->ActionsPerConfig) {
@@ -119,39 +106,19 @@
}
}
-void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
- std::string const& config,
- Indent indent)
+void cmTestGenerator::GenerateCommand(std::ostream& os,
+ std::vector<std::string> const& command,
+ std::string const& config, bool expand,
+ cmGeneratorExpression& ge,
+ cmPolicies::PolicyStatus cmp0158,
+ cmPolicies::PolicyStatus cmp0178)
{
- this->TestGenerated = true;
-
- // Set up generator expression evaluation context.
- cmGeneratorExpression ge(*this->Test->GetMakefile()->GetCMakeInstance(),
- this->Test->GetBacktrace());
-
- // Determine if policy CMP0110 is set to NEW.
- bool const quote_test_name =
- needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName());
- // Determine the number of equal-signs needed for quoting test name with
- // [==[...]==] syntax.
- std::string const equalSigns(
- 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '=');
-
- // Start the test command.
- if (quote_test_name) {
- os << indent << "add_test([" << equalSigns << "[" << this->Test->GetName()
- << "]" << equalSigns << "] ";
- } else {
- os << indent << "add_test(" << this->Test->GetName() << " ";
- }
-
// Evaluate command line arguments
cmList argv{
- this->EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config),
+ this->EvaluateCommandLineArguments(command, ge, config),
// Expand arguments if COMMAND_EXPAND_LISTS is set
- this->Test->GetCommandExpandLists() ? cmList::ExpandElements::Yes
- : cmList::ExpandElements::No,
- cmList::EmptyElements::Yes
+ expand ? cmList::ExpandElements::Yes : cmList::ExpandElements::No,
+ cmList::EmptyElements::Yes,
};
// Expanding lists on an empty command may have left it empty
if (argv.empty()) {
@@ -166,23 +133,22 @@
// Use the target file on disk.
exe = target->GetFullPath(config);
- auto addLauncher = [this, &config, &ge, &os,
- target](std::string const& propertyName) {
+ auto addLauncher = [&](std::string const& propertyName) {
cmValue launcher = target->GetProperty(propertyName);
if (!cmNonempty(launcher)) {
return;
}
auto const propVal = ge.Parse(*launcher)->Evaluate(this->LG, config);
cmList launcherWithArgs(propVal, cmList::ExpandElements::Yes,
- this->Test->GetCMP0178() == cmPolicies::NEW
+ cmp0178 == cmPolicies::NEW
? cmList::EmptyElements::Yes
: cmList::EmptyElements::No);
if (!launcherWithArgs.empty() && !launcherWithArgs[0].empty()) {
- if (this->Test->GetCMP0178() == cmPolicies::WARN) {
+ if (cmp0178 == cmPolicies::WARN) {
cmList argsWithEmptyValuesPreserved(
propVal, cmList::ExpandElements::Yes, cmList::EmptyElements::Yes);
if (launcherWithArgs != argsWithEmptyValuesPreserved) {
- this->Test->GetMakefile()->IssueMessage(
+ this->LG->GetMakefile()->IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat("The ", propertyName, " property of target '",
target->GetName(),
@@ -194,14 +160,10 @@
}
std::string launcherExe(launcherWithArgs[0]);
cmSystemTools::ConvertToUnixSlashes(launcherExe);
- os << cmOutputConverter::EscapeForCMake(launcherExe) << " ";
+ os << cmScriptGenerator::Quote(launcherExe) << " ";
for (std::string const& arg :
cmMakeRange(launcherWithArgs).advance(1)) {
- if (arg.empty()) {
- os << "\"\" ";
- } else {
- os << cmOutputConverter::EscapeForCMake(arg) << " ";
- }
+ os << cmScriptGenerator::Quote(arg) << " ";
}
}
};
@@ -210,7 +172,7 @@
addLauncher("TEST_LAUNCHER");
// Prepend with the emulator when cross compiling if required.
- if (!this->GetTest()->GetCMP0158IsNew() ||
+ if (cmp0158 != cmPolicies::NEW ||
this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING")) {
addLauncher("CROSSCOMPILING_EMULATOR");
}
@@ -220,49 +182,45 @@
}
// Generate the command line with full escapes.
- os << cmOutputConverter::EscapeForCMake(exe);
+ os << cmScriptGenerator::Quote(exe);
for (auto const& arg : cmMakeRange(argv).advance(1)) {
- os << " " << cmOutputConverter::EscapeForCMake(arg);
+ os << " " << cmScriptGenerator::Quote(arg);
}
+}
- // Finish the test command.
+void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
+ std::string const& config,
+ Indent indent)
+{
+ this->TestGenerated = true;
+
+ // Set up generator expression evaluation context.
+ cmGeneratorExpression ge(*this->Test->GetMakefile()->GetCMakeInstance(),
+ this->Test->GetBacktrace());
+
+ auto const test_name = TestName(this->Test);
+ os << indent << "add_test(" << test_name << ' ';
+ this->GenerateCommand(
+ os, this->Test->GetCommand(), config, this->Test->GetCommandExpandLists(),
+ ge, this->GetTest()->GetCMP0158(), this->Test->GetCMP0178());
os << ")\n";
// Output properties for the test.
- if (quote_test_name) {
- os << indent << "set_tests_properties([" << equalSigns << "["
- << this->Test->GetName() << "]" << equalSigns << "] PROPERTIES ";
- } else {
- os << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
- }
+ os << indent << "set_tests_properties(" << test_name << " PROPERTIES ";
for (auto const& i : this->Test->GetProperties().GetList()) {
os << " " << i.first << " "
- << cmOutputConverter::EscapeForCMake(
+ << cmScriptGenerator::Quote(
ge.Parse(i.second)->Evaluate(this->LG, config));
}
- this->GenerateInternalProperties(os);
+ os << ' ';
+ this->GenerateBacktrace(os, this->Test->GetBacktrace());
os << ")\n";
}
void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent)
{
- // Determine if policy CMP0110 is set to NEW.
- bool const quote_test_name =
- needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName());
- // Determine the number of equal-signs needed for quoting test name with
- // [==[...]==] syntax.
- std::string const equalSigns(
- 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '=');
-
- if (quote_test_name) {
- os << indent << "add_test([" << equalSigns << "[" << this->Test->GetName()
- << "]" << equalSigns << "] NOT_AVAILABLE)\n";
- } else {
- os << indent << "add_test(" << this->Test->GetName()
- << " NOT_AVAILABLE)\n";
- }
+ os << indent << "add_test(" << TestName(this->Test) << " NOT_AVAILABLE)\n";
}
bool cmTestGenerator::NeedsScriptNoConfig() const
@@ -277,27 +235,14 @@
{
this->TestGenerated = true;
- // Determine if policy CMP0110 is set to NEW.
- bool const quote_test_name =
- needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName());
- // Determine the number of equal-signs needed for quoting test name with
- // [==[...]==] syntax.
- std::string const equalSigns(
- 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '=');
+ auto const test_name = TestName(this->Test);
// Get the test command line to be executed.
std::vector<std::string> const& command = this->Test->GetCommand();
std::string exe = command[0];
cmSystemTools::ConvertToUnixSlashes(exe);
- if (quote_test_name) {
- fout << indent << "add_test([" << equalSigns << "["
- << this->Test->GetName() << "]" << equalSigns << "] \"" << exe
- << "\"";
- } else {
- fout << indent << "add_test(" << this->Test->GetName() << " \"" << exe
- << "\"";
- }
+ fout << indent << "add_test(" << test_name << " \"" << exe << "\"";
for (std::string const& arg : cmMakeRange(command).advance(1)) {
// Just double-quote all arguments so they are re-parsed
@@ -317,31 +262,23 @@
fout << ")\n";
// Output properties for the test.
- if (quote_test_name) {
- fout << indent << "set_tests_properties([" << equalSigns << "["
- << this->Test->GetName() << "]" << equalSigns << "] PROPERTIES ";
- } else {
- fout << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
- }
+ fout << indent << "set_tests_properties(" << test_name << " PROPERTIES ";
for (auto const& i : this->Test->GetProperties().GetList()) {
- fout << " " << i.first << " "
- << cmOutputConverter::EscapeForCMake(i.second);
+ fout << " " << i.first << " " << cmScriptGenerator::Quote(i.second);
}
- this->GenerateInternalProperties(fout);
+ fout << ' ';
+ this->GenerateBacktrace(fout, this->Test->GetBacktrace());
fout << ")\n";
}
-void cmTestGenerator::GenerateInternalProperties(std::ostream& os)
+void cmTestGenerator::GenerateBacktrace(std::ostream& os,
+ cmListFileBacktrace bt)
{
- cmListFileBacktrace bt = this->Test->GetBacktrace();
if (bt.Empty()) {
return;
}
- os << " "
- << "_BACKTRACE_TRIPLES"
- << " \"";
+ os << "_BACKTRACE_TRIPLES \"";
bool prependTripleSeparator = false;
while (!bt.Empty()) {
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h
index b728ba3..cd59b11 100644
--- a/Source/cmTestGenerator.h
+++ b/Source/cmTestGenerator.h
@@ -8,8 +8,10 @@
#include <string>
#include <vector>
+#include "cmPolicies.h"
#include "cmScriptGenerator.h"
+class cmListFileBacktrace;
class cmGeneratorExpression;
class cmLocalGenerator;
class cmTest;
@@ -37,13 +39,18 @@
cmTest* GetTest() const;
private:
- void GenerateInternalProperties(std::ostream& os);
std::vector<std::string> EvaluateCommandLineArguments(
std::vector<std::string> const& argv, cmGeneratorExpression& ge,
std::string const& config) const;
protected:
- void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
+ void GenerateBacktrace(std::ostream& os, cmListFileBacktrace bt);
+ void GenerateCommand(std::ostream& os,
+ std::vector<std::string> const& command,
+ std::string const& config, bool expand,
+ cmGeneratorExpression& ge,
+ cmPolicies::PolicyStatus cmp0158 = cmPolicies::NEW,
+ cmPolicies::PolicyStatus cmp0178 = cmPolicies::NEW);
void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateScriptForConfig(std::ostream& os, std::string const& config,
Indent indent) override;
diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx
index 05d9361..44fd852 100644
--- a/Source/cmUVProcessChain.cxx
+++ b/Source/cmUVProcessChain.cxx
@@ -159,6 +159,13 @@
return *this;
}
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetEnvironment(
+ std::vector<std::string> env)
+{
+ this->Environment = std::move(env);
+ return *this;
+}
+
cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetDetached()
{
this->Detached = true;
@@ -370,6 +377,16 @@
options.cwd = this->Builder->WorkingDirectory.c_str();
}
+ auto env = std::vector<char const*>{};
+ if (!this->Builder->Environment.empty()) {
+ env.reserve(this->Builder->Environment.size() + 1);
+ for (auto const& var : this->Builder->Environment) {
+ env.push_back(var.c_str());
+ }
+ env.push_back(nullptr);
+ options.env = const_cast<char**>(env.data());
+ }
+
std::array<uv_stdio_container_t, 3> stdio;
if (first) {
stdio[0] = this->InputStreamData.Stdio;
diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h
index 2116eb2..2b9671f 100644
--- a/Source/cmUVProcessChain.h
+++ b/Source/cmUVProcessChain.h
@@ -38,6 +38,7 @@
cmUVProcessChainBuilder& SetExternalStream(Stream stdio, int fd);
cmUVProcessChainBuilder& SetExternalStream(Stream stdio, FILE* stream);
cmUVProcessChainBuilder& SetWorkingDirectory(std::string dir);
+ cmUVProcessChainBuilder& SetEnvironment(std::vector<std::string> env);
cmUVProcessChainBuilder& SetDetached();
uv_loop_t* GetLoop() const;
@@ -68,6 +69,7 @@
std::array<StdioConfiguration, 3> Stdio;
std::vector<ProcessConfiguration> Processes;
std::string WorkingDirectory;
+ std::vector<std::string> Environment;
bool MergedBuiltinStreams = false;
bool Detached = false;
uv_loop_t* Loop = nullptr;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 364fd56..c6f7432 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -27,9 +27,11 @@
#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
-#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorFileSet.h"
+#include "cmGeneratorFileSets.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -1839,7 +1841,7 @@
for (std::string const& d : ccg.GetDepends()) {
std::string dep;
- if (lg->GetRealDependency(d, c, dep)) {
+ if (lg->GetRealDependency(d, c, dep, command.GetCMP0212Status())) {
if (!unique_inputs.insert(dep).second) {
// already listed
continue;
@@ -2628,6 +2630,9 @@
case cmGeneratorTarget::SourceKindResx:
this->ResxObjs.push_back(si.Source);
break;
+ case cmGeneratorTarget::SourceKindRustMainCrateRoot:
+ tool = "None";
+ break;
case cmGeneratorTarget::SourceKindXaml:
this->XamlObjs.push_back(si.Source);
break;
@@ -2711,13 +2716,13 @@
if (si.Kind == cmGeneratorTarget::SourceKindObjectSource ||
si.Kind == cmGeneratorTarget::SourceKindUnityBatched) {
this->OutputSourceSpecificFlags(e2, si.Source);
- } else if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ } else if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
this->GeneratorTarget->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Target \"", this->GeneratorTarget->GetName(),
"\" has source file\n ", si.Source->GetFullPath(),
- "\nin a \"FILE_SET TYPE CXX_MODULES\" but it is not "
- "scheduled for compilation."));
+ "\nin a \"FILE_SET TYPE ", cm::FileSetMetadata::CXX_MODULES,
+ "\" but it is not scheduled for compilation."));
}
if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
e2.Element("PrecompiledHeader", "NotUsing");
@@ -2753,13 +2758,13 @@
}
this->FinishWritingSource(e2, toolSettings);
- } else if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ } else if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
this->GeneratorTarget->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Target \"", this->GeneratorTarget->GetName(),
"\" has source file\n ", si.Source->GetFullPath(),
- "\nin a \"FILE_SET TYPE CXX_MODULES\" but it is not "
- "scheduled for compilation."));
+ "\nin a \"FILE_SET TYPE ", cm::FileSetMetadata::CXX_MODULES,
+ "\" but it is not scheduled for compilation."));
}
}
@@ -2879,14 +2884,36 @@
configDefines += *ccdefs;
}
+ // lookup for the associated file set, if any.
+ auto const* fileSet =
+ this->GeneratorTarget->GetFileSetForSource(config, source);
+ bool fileSetBelongsToTarget = false;
+ std::vector<std::string> fsOptions;
+ std::vector<std::string> fsDefines;
+ std::vector<std::string> fsIncludes;
+
+ if (fileSet) {
+ fileSetBelongsToTarget = fileSet->BelongsTo(this->GeneratorTarget);
+ fsOptions =
+ cm::remove_BT(fileSetBelongsToTarget
+ ? fileSet->GetCompileOptions(config, lang)
+ : fileSet->GetInterfaceCompileOptions(config, lang));
+ fsDefines = cm::remove_BT(
+ fileSetBelongsToTarget
+ ? fileSet->GetCompileDefinitions(config, lang)
+ : fileSet->GetInterfaceCompileDefinitions(config, lang));
+ fsIncludes = cm::remove_BT(
+ fileSetBelongsToTarget
+ ? fileSet->GetIncludeDirectories(config, lang)
+ : fileSet->GetInterfaceIncludeDirectories(config, lang));
+ }
+
bool const shouldScanForModules = lang == "CXX"_s &&
this->GeneratorTarget->NeedDyndepForSource(lang, config, source);
- auto const* fs =
- this->GeneratorTarget->GetFileSetForSource(config, source);
char const* compileAsPerConfig = compileAs;
- if (fs && fs->GetType() == "CXX_MODULES"_s) {
+ if (fileSet && fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES) {
if (lang == "CXX"_s) {
- if (fs->GetType() == "CXX_MODULES"_s) {
+ if (fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES) {
isCppModule = true;
if (shouldScanForModules &&
this->GlobalGenerator->IsScanDependenciesSupported()) {
@@ -2905,7 +2932,7 @@
cmStrCat(
"Target \"", this->GeneratorTarget->Target->GetName(),
"\" contains the source\n ", source->GetFullPath(),
- "\nin a file set of type \"", fs->GetType(),
+ "\nin a file set of type \"", fileSet->GetType(),
R"(" but the source is not classified as a "CXX" source.)"));
}
}
@@ -2931,9 +2958,10 @@
// if we have flags or defines for this config then
// use them
- if (!flags.empty() || !options.empty() || !configDefines.empty() ||
- !includes.empty() || compileAsPerConfig || noWinRT ||
- !options.empty() || needsPCHFlags ||
+ if (!flags.empty() || !options.empty() || !fsOptions.empty() ||
+ !configDefines.empty() || !fsDefines.empty() || !includes.empty() ||
+ !fsIncludes.empty() || compileAsPerConfig || noWinRT ||
+ needsPCHFlags ||
(shouldScanForModules !=
this->ScanSourceForModuleDependencies[config])) {
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
@@ -3006,8 +3034,8 @@
}
}
+ std::string expandedOptions;
if (!options.empty()) {
- std::string expandedOptions;
if (configDependentOptions) {
this->LocalGenerator->AppendCompileOptions(
expandedOptions,
@@ -3015,6 +3043,12 @@
} else {
this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
}
+ }
+ // Add flags from file set properties.
+ if (!fsOptions.empty()) {
+ this->LocalGenerator->AppendCompileOptions(expandedOptions, fsOptions);
+ }
+ if (!expandedOptions.empty()) {
clOptions.Parse(expandedOptions);
}
if (clOptions.HasFlag("DisableSpecificWarnings")) {
@@ -3030,7 +3064,16 @@
} else {
clOptions.AddDefines(configDefines);
}
+ // Add defines from file set properties.
+ if (!fsDefines.empty()) {
+ clOptions.AddDefines(fsDefines);
+ }
std::vector<std::string> includeList;
+ // Add include directories from file set properties.
+ if (!fsIncludes.empty()) {
+ this->LocalGenerator->AppendIncludeDirectories(includeList, fsIncludes,
+ *source);
+ }
if (configDependentIncludes) {
this->LocalGenerator->AppendIncludeDirectories(
includeList,
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 3b311e0..2a588f6 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -48,6 +48,7 @@
# include "cmDebuggerPosixPipeConnection.h"
# endif //_WIN32
#endif
+#include "cmDiagnostics.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
#include "cmDuration.h"
@@ -177,6 +178,19 @@
}
#endif
+void warnDeprecated(cm::string_view oldOption, cm::string_view newOption)
+{
+ std::cerr << "The "_s << oldOption << " option is deprecated. Use "_s
+ << newOption << " instead.\n"_s;
+}
+
+std::string normalizeCliWarningName(cm::string_view cliName)
+{
+ std::string out = cmStrCat("CMD_"_s, cmSystemTools::UpperCase(cliName));
+ std::replace(out.begin(), out.end(), '-', '_');
+ return out;
+}
+
bool cmakeCheckStampFile(std::string const& stampName)
{
// The stamp file does not exist. Use the stamp dependencies to
@@ -269,9 +283,16 @@
return true;
}
+bool isDiagnosticSet(cmStateSnapshot const& state,
+ cmDiagnosticCategory category)
+{
+ constexpr cmDiagnosticAction unset = cmDiagnostics::Undefined;
+ return (state.GetDiagnostic(category, unset) == unset);
+}
+
} // namespace
-cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[19] = {
+cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[15] = {
{ "-S <path-to-source>", "Explicitly specify a source directory." },
{ "-B <path-to-build>", "Explicitly specify a build directory." },
{ "-C <initial-cache>", "Pre-load a script to populate the cache." },
@@ -285,18 +306,11 @@
"Specify install directory [CMAKE_INSTALL_PREFIX]." },
{ "--project-file <project-file-name>",
"Specify an alternate project file name." },
- { "-Wdev", "Enable developer warnings." },
- { "-Wno-dev", "Suppress developer warnings." },
- { "-Werror=dev", "Make developer warnings errors." },
- { "-Wno-error=dev", "Make developer warnings not errors." },
- { "-Wdeprecated", "Enable deprecation warnings." },
- { "-Wno-deprecated", "Suppress deprecation warnings." },
- { "-Werror=deprecated",
- "Make deprecated macro and function warnings "
- "errors." },
- { "-Wno-error=deprecated",
- "Make deprecated macro and function warnings "
- "not errors." }
+ { "-W<category>", "Enable the specified category of warnings." },
+ { "-Wno-<category>", "Suppress the specified category of warnings." },
+ { "-Werror=<category>", "Make the specified category of warnings errors." },
+ { "-Wno-error=<category>",
+ "Make the specified category of warnings not errors." },
};
cmake::cmake(cmState::Role role, cmState::TryCompile isTryCompile)
@@ -471,7 +485,7 @@
void cmake::CleanupCommandsAndMacros()
{
- this->CurrentSnapshot = this->State->Reset();
+ this->CurrentSnapshot = this->State->Reset(this->CurrentSnapshot);
this->State->RemoveUserDefinedCommands();
this->CurrentSnapshot.SetDefaultDefinitions();
// FIXME: InstalledFiles probably belongs in the global generator.
@@ -479,22 +493,27 @@
}
#ifndef CMAKE_BOOTSTRAP
-void cmake::SetWarningFromPreset(std::string const& name,
- cm::optional<bool> warning,
- cm::optional<bool> error)
+void cmake::SetDiagnosticsFromPreset(
+ std::map<cmDiagnosticCategory, bool> const& warnings,
+ std::map<cmDiagnosticCategory, bool> const& errors)
{
- if (warning) {
- if (*warning) {
- this->DiagLevels[name] = std::max(this->DiagLevels[name], DIAG_WARN);
+ for (auto const& wi : warnings) {
+ if (wi.second) {
+ this->CurrentSnapshot.PromoteDiagnostic( // clang-format: break
+ wi.first, cmDiagnostics::Warn, true);
} else {
- this->DiagLevels[name] = DIAG_IGNORE;
+ this->CurrentSnapshot.DemoteDiagnostic( // clang-format: break
+ wi.first, cmDiagnostics::Ignore, true);
}
}
- if (error) {
- if (*error) {
- this->DiagLevels[name] = DIAG_ERROR;
+
+ for (auto const& ei : errors) {
+ if (ei.second) {
+ this->CurrentSnapshot.PromoteDiagnostic( // clang-format: break
+ ei.first, cmDiagnostics::SendError, true);
} else {
- this->DiagLevels[name] = std::min(this->DiagLevels[name], DIAG_WARN);
+ this->CurrentSnapshot.DemoteDiagnostic( // clang-format: break
+ ei.first, cmDiagnostics::Warn, true);
}
}
}
@@ -604,44 +623,51 @@
return true;
};
- auto WarningLambda = [](cm::string_view entry, cmake* state) -> bool {
+ auto WarningLambda = [](cm::string_view option, cmake* state) -> bool {
bool foundNo = false;
bool foundError = false;
- if (cmHasLiteralPrefix(entry, "no-")) {
+ cm::string_view cname = option;
+ if (cmHasLiteralPrefix(cname, "no-")) {
foundNo = true;
- entry.remove_prefix(3);
+ cname.remove_prefix(3);
}
- if (cmHasLiteralPrefix(entry, "error=")) {
+ if (cmHasLiteralPrefix(cname, "error=")) {
foundError = true;
- entry.remove_prefix(6);
+ cname.remove_prefix(6);
}
- if (entry.empty()) {
+ if (cname.empty()) {
cmSystemTools::Error("No warning name provided.");
return false;
}
- std::string const name = std::string(entry);
- if (!foundNo && !foundError) {
- // -W<name>
- state->DiagLevels[name] = std::max(state->DiagLevels[name], DIAG_WARN);
- } else if (foundNo && !foundError) {
- // -Wno<name>
- state->DiagLevels[name] = DIAG_IGNORE;
- } else if (!foundNo && foundError) {
- // -Werror=<name>
- state->DiagLevels[name] = DIAG_ERROR;
+ cm::optional<cmDiagnosticCategory> category;
+ if (cname == "dev"_s) {
+ warnDeprecated(
+ option,
+ cmStrCat("-W"_s, option.substr(0, option.size() - 3), "author"_s));
+ category = cmDiagnostics::CMD_AUTHOR;
} else {
- // -Wno-error=<name>
- // This can downgrade an error to a warning, but should not enable
- // or disable a warning in the first place.
- auto dli = state->DiagLevels.find(name);
- if (dli != state->DiagLevels.end()) {
- dli->second = std::min(dli->second, DIAG_WARN);
+ category =
+ cmDiagnostics::GetDiagnosticCategory(normalizeCliWarningName(cname));
+ if (!category) {
+ cmSystemTools::Error(
+ cmStrCat("The warning category \""_s, cname, "\" is not known."));
+ return false;
}
}
+
+ if (foundNo) {
+ state->CurrentSnapshot.DemoteDiagnostic(
+ *category, foundError ? cmDiagnostics::Warn : cmDiagnostics::Ignore,
+ true);
+ } else {
+ state->CurrentSnapshot.PromoteDiagnostic(
+ *category, foundError ? cmDiagnostics::SendError : cmDiagnostics::Warn,
+ true);
+ }
return true;
};
@@ -785,12 +811,15 @@
void cmake::ProcessCacheArg(std::string const& var, std::string const& value,
cmStateEnums::CacheEntryType type)
{
+ cmDiagnosticAction const warnUnusedCli =
+ this->CurrentSnapshot.GetDiagnostic(cmDiagnostics::CMD_UNUSED_CLI);
+
// The value is transformed if it is a filepath for example, so
// we can't compare whether the value is already in the cache until
// after we call AddCacheEntry.
bool haveValue = false;
std::string cachedValue;
- if (this->WarnUnusedCli) {
+ if (warnUnusedCli != cmDiagnostics::Ignore) {
if (cmValue v = this->State->GetInitializedCacheValue(var)) {
haveValue = true;
cachedValue = *v;
@@ -800,7 +829,7 @@
this->AddCacheEntry(
var, value, "No help, variable specified on the command line.", type);
- if (this->WarnUnusedCli) {
+ if (warnUnusedCli != cmDiagnostics::Ignore) {
if (!haveValue ||
cachedValue != *this->State->GetInitializedCacheValue(var)) {
this->WatchUnusedCli(var);
@@ -823,7 +852,7 @@
// read in the list file to fill the cache
if (!path.empty()) {
- this->CurrentSnapshot = this->State->Reset();
+ this->CurrentSnapshot = this->State->Reset(this->CurrentSnapshot);
cmStateSnapshot snapshot = this->GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentBinary(this->GetHomeOutputDirectory());
snapshot.GetDirectory().SetCurrentSource(this->GetHomeDirectory());
@@ -967,19 +996,6 @@
cmSystemTools::GetEnvVar("CMAKE_AUTOGEN_INTERMEDIATE_DIR_STRATEGY");
}
-namespace {
-enum class ListPresets
-{
- None,
- Configure,
- Build,
- Test,
- Package,
- Workflow,
- All,
-};
-}
-
// Parse the args
void cmake::SetArgs(std::vector<std::string> const& args)
{
@@ -1284,22 +1300,24 @@
state->SetTrace(true);
return true;
} },
- CommandArgument{ "--warn-uninitialized", CommandArgument::Values::Zero,
- [](std::string const&, cmake* state) -> bool {
- std::cout << "Warn about uninitialized values.\n";
- state->SetWarnUninitialized(true);
- return true;
- } },
+ CommandArgument{
+ "--warn-uninitialized", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ warnDeprecated("--warn-uninitialized"_s, "-Wuninitialized"_s);
+ state->CurrentSnapshot.PromoteDiagnostic(
+ cmDiagnostics::CMD_UNINITIALIZED, cmDiagnostics::Warn, true);
+ return true;
+ } },
CommandArgument{ "--warn-unused-vars", CommandArgument::Values::Zero,
IgnoreAndTrueLambda }, // Option was removed.
- CommandArgument{ "--no-warn-unused-cli", CommandArgument::Values::Zero,
- [](std::string const&, cmake* state) -> bool {
- std::cout
- << "Not searching for unused variables given on the "
- "command line.\n";
- state->SetWarnUnusedCli(false);
- return true;
- } },
+ CommandArgument{
+ "--no-warn-unused-cli", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ warnDeprecated("--no-warn-unused-cli"_s, "-Wno-unused-cli"_s);
+ state->CurrentSnapshot.DemoteDiagnostic(cmDiagnostics::CMD_UNUSED_CLI,
+ cmDiagnostics::Ignore, true);
+ return true;
+ } },
CommandArgument{
"--check-system-vars", CommandArgument::Values::Zero,
[](std::string const&, cmake* state) -> bool {
@@ -1571,156 +1589,7 @@
#if !defined(CMAKE_BOOTSTRAP)
if (listPresets != ListPresets::None || !presetName.empty()) {
- cmCMakePresetsGraph presetsGraph;
- auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory());
- if (result != true) {
- std::string errorMsg =
- cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
- ":\n", presetsGraph.parseState.GetErrorMessage());
- cmSystemTools::Error(errorMsg);
- return;
- }
-
- if (listPresets != ListPresets::None) {
- if (listPresets == ListPresets::Configure) {
- this->PrintPresetList(presetsGraph);
- } else if (listPresets == ListPresets::Build) {
- presetsGraph.PrintBuildPresetList();
- } else if (listPresets == ListPresets::Test) {
- presetsGraph.PrintTestPresetList();
- } else if (listPresets == ListPresets::Package) {
- presetsGraph.PrintPackagePresetList();
- } else if (listPresets == ListPresets::Workflow) {
- presetsGraph.PrintWorkflowPresetList();
- } else if (listPresets == ListPresets::All) {
- presetsGraph.PrintAllPresets();
- }
-
- this->State->SetRoleToHelpForListPresets();
- return;
- }
-
- auto preset = presetsGraph.ConfigurePresets.find(presetName);
- if (preset == presetsGraph.ConfigurePresets.end()) {
- cmSystemTools::Error(cmStrCat("No such preset in ",
- this->GetHomeDirectory(), ": \"",
- presetName, '"'));
- this->PrintPresetList(presetsGraph);
- return;
- }
- if (preset->second.Unexpanded.Hidden) {
- cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
- this->GetHomeDirectory(), ": \"",
- presetName, '"'));
- this->PrintPresetList(presetsGraph);
- return;
- }
- auto const& expandedPreset = preset->second.Expanded;
- if (!expandedPreset) {
- cmSystemTools::Error(cmStrCat("Could not evaluate preset \"",
- preset->second.Unexpanded.Name,
- "\": Invalid macro expansion"));
- return;
- }
- if (!expandedPreset->ConditionResult) {
- cmSystemTools::Error(cmStrCat("Could not use disabled preset \"",
- preset->second.Unexpanded.Name, '"'));
- return;
- }
-
- if (!this->State->IsCacheLoaded() && !haveBArg &&
- !expandedPreset->BinaryDir.empty()) {
- this->SetHomeOutputDirectory(expandedPreset->BinaryDir);
- }
- if (!this->GlobalGenerator && !expandedPreset->Generator.empty()) {
- if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator)) {
- return;
- }
- }
- this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
- this->UnprocessedPresetEnvironment = expandedPreset->Environment;
-
- if (!expandedPreset->InstallDir.empty() &&
- !this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX")) {
- this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = {
- "PATH", expandedPreset->InstallDir
- };
- }
- if (!expandedPreset->ToolchainFile.empty() &&
- !this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) {
- this->UnprocessedPresetVariables["CMAKE_TOOLCHAIN_FILE"] = {
- "FILEPATH", expandedPreset->ToolchainFile
- };
- }
-
- if (!expandedPreset->ArchitectureStrategy ||
- expandedPreset->ArchitectureStrategy ==
- cmCMakePresetsGraph::ArchToolsetStrategy::Set) {
- if (!this->GeneratorPlatformSet &&
- !expandedPreset->Architecture.empty()) {
- this->SetGeneratorPlatform(expandedPreset->Architecture);
- }
- }
- if (!expandedPreset->ToolsetStrategy ||
- expandedPreset->ToolsetStrategy ==
- cmCMakePresetsGraph::ArchToolsetStrategy::Set) {
- if (!this->GeneratorToolsetSet && !expandedPreset->Toolset.empty()) {
- this->SetGeneratorToolset(expandedPreset->Toolset);
- }
- }
-
- if (!expandedPreset->GraphVizFile.empty()) {
- if (this->GraphVizFile.empty()) {
- this->SetGraphVizFile(
- cmSystemTools::CollapseFullPath(expandedPreset->GraphVizFile));
- }
- }
-
- this->SetWarningFromPreset("dev", expandedPreset->WarnDev,
- expandedPreset->ErrorDev);
- this->SetWarningFromPreset("deprecated", expandedPreset->WarnDeprecated,
- expandedPreset->ErrorDeprecated);
- if (expandedPreset->WarnUninitialized == true) {
- this->SetWarnUninitialized(true);
- }
- if (expandedPreset->WarnUnusedCli == false) {
- this->SetWarnUnusedCli(false);
- }
- if (expandedPreset->WarnSystemVars == true) {
- this->SetCheckSystemVars(true);
- }
- if (expandedPreset->DebugOutput == true) {
- this->SetDebugOutputOn(true);
- }
- if (expandedPreset->DebugTryCompile == true) {
- this->DebugTryCompileOn();
- }
- if (expandedPreset->DebugFind == true) {
- this->SetDebugFindOutput(true);
- }
- if (expandedPreset->TraceMode &&
- expandedPreset->TraceMode !=
- cmCMakePresetsGraph::TraceEnableMode::Disable) {
- this->SetTrace(true);
- if (expandedPreset->TraceMode ==
- cmCMakePresetsGraph::TraceEnableMode::Expand) {
- this->SetTraceExpand(true);
- }
- }
- if (expandedPreset->TraceFormat) {
- this->SetTrace(true);
- this->SetTraceFormat(*expandedPreset->TraceFormat);
- }
- if (!expandedPreset->TraceSource.empty()) {
- this->SetTrace(true);
- for (std::string const& filePaths : expandedPreset->TraceSource) {
- this->AddTraceSource(filePaths);
- }
- }
- if (!expandedPreset->TraceRedirect.empty()) {
- this->SetTrace(true);
- this->SetTraceFile(expandedPreset->TraceRedirect);
- }
+ this->SetArgsFromPreset(presetName, listPresets, haveBArg);
}
#endif
}
@@ -2135,6 +2004,154 @@
}
#ifndef CMAKE_BOOTSTRAP
+bool cmake::SetArgsFromPreset(std::string const& presetName,
+ ListPresets listPresets, bool haveBinaryDirArg)
+{
+ cmCMakePresetsGraph presetsGraph;
+ auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory());
+ if (result != true) {
+ std::string errorMsg =
+ cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ":\n",
+ presetsGraph.parseState.GetErrorMessage());
+ cmSystemTools::Error(errorMsg);
+ return false;
+ }
+
+ if (listPresets != ListPresets::None) {
+ if (listPresets == ListPresets::Configure) {
+ this->PrintPresetList(presetsGraph);
+ } else if (listPresets == ListPresets::Build) {
+ presetsGraph.PrintBuildPresetList();
+ } else if (listPresets == ListPresets::Test) {
+ presetsGraph.PrintTestPresetList();
+ } else if (listPresets == ListPresets::Package) {
+ presetsGraph.PrintPackagePresetList();
+ } else if (listPresets == ListPresets::Workflow) {
+ presetsGraph.PrintWorkflowPresetList();
+ } else if (listPresets == ListPresets::All) {
+ presetsGraph.PrintAllPresets();
+ }
+
+ this->State->SetRoleToHelpForListPresets();
+ return false;
+ }
+
+ auto preset = presetsGraph.ConfigurePresets.find(presetName);
+ if (preset == presetsGraph.ConfigurePresets.end()) {
+ cmSystemTools::Error(cmStrCat("No such preset in ",
+ this->GetHomeDirectory(), ": \"", presetName,
+ '"'));
+ this->PrintPresetList(presetsGraph);
+ return false;
+ }
+ if (preset->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
+ this->GetHomeDirectory(), ": \"", presetName,
+ '"'));
+ this->PrintPresetList(presetsGraph);
+ return false;
+ }
+ auto const& expandedPreset = preset->second.Expanded;
+ if (!expandedPreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate preset \"",
+ preset->second.Unexpanded.Name,
+ "\": Invalid macro expansion"));
+ return false;
+ }
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Could not use disabled preset \"",
+ preset->second.Unexpanded.Name, '"'));
+ return false;
+ }
+
+ if (!this->State->IsCacheLoaded() && !haveBinaryDirArg &&
+ !expandedPreset->BinaryDir.empty()) {
+ this->SetHomeOutputDirectory(expandedPreset->BinaryDir);
+ }
+ if (!this->GlobalGenerator && !expandedPreset->Generator.empty()) {
+ if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator)) {
+ return false;
+ }
+ }
+ this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
+ this->UnprocessedPresetEnvironment = expandedPreset->Environment;
+
+ if (!expandedPreset->InstallDir.empty() &&
+ !this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX")) {
+ this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = {
+ "PATH", expandedPreset->InstallDir
+ };
+ }
+ if (!expandedPreset->ToolchainFile.empty() &&
+ !this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) {
+ this->UnprocessedPresetVariables["CMAKE_TOOLCHAIN_FILE"] = {
+ "FILEPATH", expandedPreset->ToolchainFile
+ };
+ }
+
+ if (!expandedPreset->ArchitectureStrategy ||
+ expandedPreset->ArchitectureStrategy ==
+ cmCMakePresetsGraph::ArchToolsetStrategy::Set) {
+ if (!this->GeneratorPlatformSet && !expandedPreset->Architecture.empty()) {
+ this->SetGeneratorPlatform(expandedPreset->Architecture);
+ }
+ }
+ if (!expandedPreset->ToolsetStrategy ||
+ expandedPreset->ToolsetStrategy ==
+ cmCMakePresetsGraph::ArchToolsetStrategy::Set) {
+ if (!this->GeneratorToolsetSet && !expandedPreset->Toolset.empty()) {
+ this->SetGeneratorToolset(expandedPreset->Toolset);
+ }
+ }
+
+ if (!expandedPreset->GraphVizFile.empty()) {
+ if (this->GraphVizFile.empty()) {
+ this->SetGraphVizFile(
+ cmSystemTools::CollapseFullPath(expandedPreset->GraphVizFile));
+ }
+ }
+
+ this->SetDiagnosticsFromPreset(expandedPreset->Warnings,
+ expandedPreset->Errors);
+ if (expandedPreset->WarnSystemVars == true) {
+ this->SetCheckSystemVars(true);
+ }
+ if (expandedPreset->DebugOutput == true) {
+ this->SetDebugOutputOn(true);
+ }
+ if (expandedPreset->DebugTryCompile == true) {
+ this->DebugTryCompileOn();
+ }
+ if (expandedPreset->DebugFind == true) {
+ this->SetDebugFindOutput(true);
+ }
+ if (expandedPreset->TraceMode &&
+ expandedPreset->TraceMode !=
+ cmCMakePresetsGraph::TraceEnableMode::Disable) {
+ this->SetTrace(true);
+ if (expandedPreset->TraceMode ==
+ cmCMakePresetsGraph::TraceEnableMode::Expand) {
+ this->SetTraceExpand(true);
+ }
+ }
+ if (expandedPreset->TraceFormat) {
+ this->SetTrace(true);
+ this->SetTraceFormat(*expandedPreset->TraceFormat);
+ }
+ if (!expandedPreset->TraceSource.empty()) {
+ this->SetTrace(true);
+ for (std::string const& filePaths : expandedPreset->TraceSource) {
+ this->AddTraceSource(filePaths);
+ }
+ }
+ if (!expandedPreset->TraceRedirect.empty()) {
+ this->SetTrace(true);
+ this->SetTraceFile(expandedPreset->TraceRedirect);
+ }
+
+ return true;
+}
+
void cmake::PrintPresetList(cmCMakePresetsGraph const& graph) const
{
std::vector<GeneratorInfo> generators;
@@ -2376,78 +2393,133 @@
auto profilingRAII = this->CreateProfilingEntry("project", "configure");
#endif
- DiagLevel diagLevel;
+ // We now need to harmonize the previous initial diagnostic state with any
+ // changes requested via command line options. This is a bit tricky, because
+ // we need to underlay what is specified by the cache beneath whatever state
+ // has been built from command line processing.
- if (this->DiagLevels.count("deprecated") == 1) {
+ cmDiagnosticAction deprecated = this->CurrentSnapshot.GetDiagnostic(
+ cmDiagnostics::CMD_DEPRECATED, cmDiagnostics::Undefined);
+ bool const deprecatedAlreadySet = (deprecated != cmDiagnostics::Undefined);
- diagLevel = this->DiagLevels["deprecated"];
- if (diagLevel == DIAG_IGNORE) {
- this->SetSuppressDeprecatedWarnings(true);
- this->SetDeprecatedWarningsAsErrors(false);
- } else if (diagLevel == DIAG_WARN) {
- this->SetSuppressDeprecatedWarnings(false);
- this->SetDeprecatedWarningsAsErrors(false);
- } else if (diagLevel == DIAG_ERROR) {
- this->SetSuppressDeprecatedWarnings(false);
- this->SetDeprecatedWarningsAsErrors(true);
- }
- }
+ if (cmValue cachedDiagnostics =
+ this->State->GetCacheEntryValue("CMAKE_DIAGNOSTIC_INIT")) {
+ for (std::string const& item : cmList{ cachedDiagnostics }) {
+ std::string::size_type n = item.find('=');
+ if (n != std::string::npos) {
+ cm::string_view v = item;
+ cm::optional<cmDiagnosticCategory> const& category =
+ cmDiagnostics::GetDiagnosticCategory(v.substr(0, n));
+ cm::optional<cmDiagnosticAction> const& action =
+ cmDiagnostics::GetDiagnosticAction(v.substr(n + 1));
- if (this->DiagLevels.count("dev") == 1) {
- bool setDeprecatedVariables = false;
-
- cmValue cachedWarnDeprecated =
- this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
- cmValue cachedErrorDeprecated =
- this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
-
- // don't overwrite deprecated warning setting from a previous invocation
- if (!cachedWarnDeprecated && !cachedErrorDeprecated) {
- setDeprecatedVariables = true;
- }
-
- diagLevel = this->DiagLevels["dev"];
- if (diagLevel == DIAG_IGNORE) {
- this->SetSuppressDevWarnings(true);
- this->SetDevWarningsAsErrors(false);
-
- if (setDeprecatedVariables) {
- this->SetSuppressDeprecatedWarnings(true);
- this->SetDeprecatedWarningsAsErrors(false);
- }
- } else if (diagLevel == DIAG_WARN) {
- this->SetSuppressDevWarnings(false);
- this->SetDevWarningsAsErrors(false);
-
- if (setDeprecatedVariables) {
- this->SetSuppressDeprecatedWarnings(false);
- this->SetDeprecatedWarningsAsErrors(false);
- }
- } else if (diagLevel == DIAG_ERROR) {
- this->SetSuppressDevWarnings(false);
- this->SetDevWarningsAsErrors(true);
-
- if (setDeprecatedVariables) {
- this->SetSuppressDeprecatedWarnings(false);
- this->SetDeprecatedWarningsAsErrors(true);
+ if (category && action) {
+ // Only use the cache if command-line options have not modified the
+ // diagnostic.
+ if (isDiagnosticSet(this->CurrentSnapshot, *category)) {
+ this->CurrentSnapshot.SetDiagnostic(*category, *action, false);
+ }
+ }
}
}
}
- // Cache variables may have already been set by a previous invocation,
- // so we cannot rely on command line options alone. Always ensure our
- // messenger is in sync with the cache.
- cmValue value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
- this->Messenger->SetSuppressDeprecatedWarnings(value && value.IsOff());
+ cmValue cachedWarnDeprecated =
+ this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
+ if (cachedWarnDeprecated) {
+ std::cerr << "The CMAKE_WARN_DEPRECATED variable is deprecated. "
+ "Use CMAKE_DIAGNOSTIC_INIT instead.\n"_s;
+ if (cachedWarnDeprecated.IsOn()) {
+ deprecated = cmDiagnostics::Warn;
+ } else {
+ deprecated = cmDiagnostics::Ignore;
+ }
+ }
- value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
- this->Messenger->SetDeprecatedWarningsAsErrors(value.IsOn());
+ cmValue cachedErrorDeprecated =
+ this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
+ if (cachedErrorDeprecated) {
+ std::cerr << "The CMAKE_ERROR_DEPRECATED variable is deprecated. "
+ "Use CMAKE_DIAGNOSTIC_INIT instead.\n"_s;
+ if (cachedErrorDeprecated.IsOn()) {
+ deprecated = cmDiagnostics::SendError;
+ }
+ }
- value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
- this->Messenger->SetSuppressDevWarnings(value.IsOn());
+ if (!deprecatedAlreadySet && deprecated != cmDiagnostics::Undefined) {
+ // CMD_DEPRECATED was not set by command-line options, but was altered by
+ // one or both of CMAKE_{WARN,ERROR}_DEPRECATED.
+ this->CurrentSnapshot.SetDiagnostic(cmDiagnostics::CMD_DEPRECATED,
+ deprecated, false);
+ }
- value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS");
- this->Messenger->SetDevWarningsAsErrors(value && value.IsOff());
+ // Copy diagnostic state to cmMessenger.
+ switch (this->CurrentSnapshot.GetDiagnostic(cmDiagnostics::CMD_AUTHOR)) {
+ case cmDiagnostics::Ignore:
+ this->Messenger->SetSuppressDevWarnings(true);
+ this->Messenger->SetDevWarningsAsErrors(false);
+ break;
+ case cmDiagnostics::SendError:
+ case cmDiagnostics::FatalError:
+ this->Messenger->SetSuppressDevWarnings(false);
+ this->Messenger->SetDevWarningsAsErrors(true);
+ break;
+ default:
+ this->Messenger->SetSuppressDevWarnings(false);
+ this->Messenger->SetDevWarningsAsErrors(false);
+ break;
+ }
+ switch (this->CurrentSnapshot.GetDiagnostic(cmDiagnostics::CMD_DEPRECATED)) {
+ case cmDiagnostics::Ignore:
+ this->Messenger->SetSuppressDeprecatedWarnings(true);
+ this->Messenger->SetDeprecatedWarningsAsErrors(false);
+ break;
+ case cmDiagnostics::SendError:
+ case cmDiagnostics::FatalError:
+ this->Messenger->SetSuppressDeprecatedWarnings(false);
+ this->Messenger->SetDeprecatedWarningsAsErrors(true);
+ break;
+ default:
+ this->Messenger->SetSuppressDeprecatedWarnings(false);
+ this->Messenger->SetDeprecatedWarningsAsErrors(false);
+ break;
+ }
+
+ // Now write the diagnostic state back to the cache.
+ cmList diagnostics;
+ for (unsigned i = 1; i < cmDiagnostics::CategoryCount; ++i) {
+ auto const category = static_cast<cmDiagnosticCategory>(i);
+ auto const action = this->CurrentSnapshot.GetDiagnostic(category);
+
+ diagnostics.emplace_back(
+ cmStrCat(cmDiagnostics::GetCategoryString(category), '=',
+ cmDiagnostics::GetActionString(action)));
+
+ if (category == cmDiagnostics::CMD_DEPRECATED) {
+ // Set deprecated CMAKE_{WARN,ERROR}_DEPRECATED, but only in the cache,
+ // and only if they were already set in the cache.
+ if (cachedWarnDeprecated) {
+ std::string const value =
+ (action >= cmDiagnostics::Warn ? "ON" : "OFF");
+ this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value,
+ "Deprecated. Use CMAKE_DIAGNOSTIC_INIT instead.",
+ cmStateEnums::INTERNAL);
+ }
+ if (cachedErrorDeprecated) {
+ std::string const value =
+ (action >= cmDiagnostics::SendError ? "ON" : "OFF");
+ this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value,
+ "Deprecated. Use CMAKE_DIAGNOSTIC_INIT instead.",
+ cmStateEnums::INTERNAL);
+ }
+ }
+ }
+
+ this->AddCacheEntry("CMAKE_DIAGNOSTIC_INIT", cmJoin(diagnostics, ";"_s),
+ "Set initial state for CMake diagnostics; "
+ "used to persist state set by command-line options "
+ "across invocations.",
+ cmStateEnums::INTERNAL);
int ret = this->ActualConfigure();
cmValue delCacheVars =
@@ -2684,6 +2756,19 @@
}
}
+ if (!this->State->GetInitializedCacheValue(
+ "CMAKE_DISABLE_PRECOMPILE_HEADERS")) {
+ cm::optional<std::string> disablePrecompileHeaders =
+ cmSystemTools::GetEnvVar("CMAKE_DISABLE_PRECOMPILE_HEADERS");
+ if (disablePrecompileHeaders && !disablePrecompileHeaders->empty()) {
+ std::string message =
+ "Default value for DISABLE_PRECOMPILE_HEADERS of targets.";
+ this->AddCacheEntry("CMAKE_DISABLE_PRECOMPILE_HEADERS",
+ *disablePrecompileHeaders, message,
+ cmStateEnums::BOOL);
+ }
+ }
+
// reset any system configuration information, except for when we are
// InTryCompile. With TryCompile the system info is taken from the parent's
// info to save time
@@ -3189,9 +3274,7 @@
std::cout << "Generate graphviz: " << this->GraphVizFile << '\n';
this->GenerateGraphViz(this->GraphVizFile);
}
- if (this->WarnUnusedCli) {
- this->RunCheckForUnusedVariables();
- }
+ this->RunCheckForUnusedVariables();
if (cmSystemTools::GetErrorOccurredFlag()) {
#if !defined(CMAKE_BOOTSTRAP)
this->FileAPI->WriteReplies(cmFileAPI::IndexFor::FailedGenerate);
@@ -3219,16 +3302,6 @@
this->State->AddCacheEntry(key, value, helpString,
static_cast<cmStateEnums::CacheEntryType>(type));
this->UnwatchUnusedCli(key);
-
- if (key == "CMAKE_WARN_DEPRECATED"_s) {
- this->Messenger->SetSuppressDeprecatedWarnings(value && value.IsOff());
- } else if (key == "CMAKE_ERROR_DEPRECATED"_s) {
- this->Messenger->SetDeprecatedWarningsAsErrors(value.IsOn());
- } else if (key == "CMAKE_SUPPRESS_DEVELOPER_WARNINGS"_s) {
- this->Messenger->SetSuppressDevWarnings(value.IsOn());
- } else if (key == "CMAKE_SUPPRESS_DEVELOPER_ERRORS"_s) {
- this->Messenger->SetDevWarningsAsErrors(value && value.IsOff());
- }
}
bool cmake::DoWriteGlobVerifyTarget() const
@@ -3836,6 +3909,14 @@
this->Messenger->IssueMessage(t, text, backtrace);
}
+void cmake::IssueDiagnostic(cmDiagnosticCategory category,
+ std::string const& text,
+ cmStateSnapshot const& state,
+ cmListFileBacktrace const& backtrace) const
+{
+ this->Messenger->IssueDiagnostic(category, text, state, backtrace);
+}
+
std::vector<std::string> cmake::GetDebugConfigs()
{
cmList configs;
@@ -4417,117 +4498,28 @@
void cmake::RunCheckForUnusedVariables()
{
#ifndef CMAKE_BOOTSTRAP
- bool haveUnused = false;
- std::ostringstream msg;
- msg << "Manually-specified variables were not used by the project:";
- for (auto const& it : this->UsedCliVariables) {
- if (!it.second) {
- haveUnused = true;
- msg << "\n " << it.first;
+ cmDiagnosticAction const action =
+ this->CurrentSnapshot.GetDiagnostic(cmDiagnostics::CMD_UNUSED_CLI);
+ if (action != cmDiagnostics::Ignore) {
+ bool haveUnused = false;
+ std::ostringstream msg;
+ msg << "Manually-specified variables were not used by the project:";
+ for (auto const& it : this->UsedCliVariables) {
+ if (!it.second) {
+ haveUnused = true;
+ msg << "\n " << it.first;
+ }
+ }
+ if (haveUnused) {
+ this->IssueMessage(action > cmDiagnostics::Warn
+ ? MessageType::FATAL_ERROR
+ : MessageType::WARNING,
+ msg.str());
}
}
- if (haveUnused) {
- this->IssueMessage(MessageType::WARNING, msg.str());
- }
#endif
}
-bool cmake::GetSuppressDevWarnings() const
-{
- return this->Messenger->GetSuppressDevWarnings();
-}
-
-void cmake::SetSuppressDevWarnings(bool b)
-{
- std::string value;
-
- // equivalent to -Wno-dev
- if (b) {
- value = "TRUE";
- }
- // equivalent to -Wdev
- else {
- value = "FALSE";
- }
-
- this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value,
- "Suppress Warnings that are meant for"
- " the author of the CMakeLists.txt files.",
- cmStateEnums::INTERNAL);
-}
-
-bool cmake::GetSuppressDeprecatedWarnings() const
-{
- return this->Messenger->GetSuppressDeprecatedWarnings();
-}
-
-void cmake::SetSuppressDeprecatedWarnings(bool b)
-{
- std::string value;
-
- // equivalent to -Wno-deprecated
- if (b) {
- value = "FALSE";
- }
- // equivalent to -Wdeprecated
- else {
- value = "TRUE";
- }
-
- this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value,
- "Whether to issue warnings for deprecated "
- "functionality.",
- cmStateEnums::INTERNAL);
-}
-
-bool cmake::GetDevWarningsAsErrors() const
-{
- return this->Messenger->GetDevWarningsAsErrors();
-}
-
-void cmake::SetDevWarningsAsErrors(bool b)
-{
- std::string value;
-
- // equivalent to -Werror=dev
- if (b) {
- value = "FALSE";
- }
- // equivalent to -Wno-error=dev
- else {
- value = "TRUE";
- }
-
- this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value,
- "Suppress errors that are meant for"
- " the author of the CMakeLists.txt files.",
- cmStateEnums::INTERNAL);
-}
-
-bool cmake::GetDeprecatedWarningsAsErrors() const
-{
- return this->Messenger->GetDeprecatedWarningsAsErrors();
-}
-
-void cmake::SetDeprecatedWarningsAsErrors(bool b)
-{
- std::string value;
-
- // equivalent to -Werror=deprecated
- if (b) {
- value = "TRUE";
- }
- // equivalent to -Wno-error=deprecated
- else {
- value = "FALSE";
- }
-
- this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value,
- "Whether to issue deprecation errors for macros"
- " and functions.",
- cmStateEnums::INTERNAL);
-}
-
void cmake::SetDebugFindOutputPkgs(std::string const& args)
{
this->DebugFindPkgs.emplace(args);
diff --git a/Source/cmake.h b/Source/cmake.h
index 38aef9e..c2a0f05 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -19,6 +19,7 @@
#include <cmext/string_view>
#include "cmBuildArgs.h"
+#include "cmDiagnostics.h"
#include "cmDocumentationEntry.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
#include "cmInstalledFile.h"
@@ -85,13 +86,6 @@
class cmake
{
public:
- enum DiagLevel
- {
- DIAG_IGNORE,
- DIAG_WARN,
- DIAG_ERROR
- };
-
/** \brief Describes the working modes of cmake */
enum WorkingMode
{
@@ -260,7 +254,20 @@
bool CreateAndSetGlobalGenerator(std::string const& name);
#ifndef CMAKE_BOOTSTRAP
- //! Print list of configure presets
+ enum class ListPresets
+ {
+ None,
+ Configure,
+ Build,
+ Test,
+ Package,
+ Workflow,
+ All,
+ };
+
+ bool SetArgsFromPreset(std::string const& presetName,
+ ListPresets listPresets, bool haveBinaryDirArg);
+
void PrintPresetList(cmCMakePresetsGraph const& graph) const;
#endif
@@ -382,9 +389,9 @@
bool GetIsInTryCompile() const;
#ifndef CMAKE_BOOTSTRAP
- void SetWarningFromPreset(std::string const& name,
- cm::optional<bool> warning,
- cm::optional<bool> error);
+ void SetDiagnosticsFromPreset(
+ std::map<cmDiagnosticCategory, bool> const& warnings,
+ std::map<cmDiagnosticCategory, bool> const& errors);
void ProcessPresetVariables();
void PrintPresetVariables();
void ProcessPresetEnvironment();
@@ -557,10 +564,6 @@
//! Use trace from another ::cmake instance.
void SetTraceRedirect(cmake* other);
- bool GetWarnUninitialized() const { return this->WarnUninitialized; }
- void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
- bool GetWarnUnusedCli() const { return this->WarnUnusedCli; }
- void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }
bool GetCheckSystemVars() const { return this->CheckSystemVars; }
void SetCheckSystemVars(bool b) { this->CheckSystemVars = b; }
bool GetIgnoreCompileWarningAsError() const
@@ -606,54 +609,20 @@
}
#endif
- /**
- * Get the state of the suppression of developer (author) warnings.
- * Returns false, by default, if developer warnings should be shown, true
- * otherwise.
- */
- bool GetSuppressDevWarnings() const;
- /**
- * Set the state of the suppression of developer (author) warnings.
- */
- void SetSuppressDevWarnings(bool v);
-
- /**
- * Get the state of the suppression of deprecated warnings.
- * Returns false, by default, if deprecated warnings should be shown, true
- * otherwise.
- */
- bool GetSuppressDeprecatedWarnings() const;
- /**
- * Set the state of the suppression of deprecated warnings.
- */
- void SetSuppressDeprecatedWarnings(bool v);
-
- /**
- * Get the state of treating developer (author) warnings as errors.
- * Returns false, by default, if warnings should not be treated as errors,
- * true otherwise.
- */
- bool GetDevWarningsAsErrors() const;
- /**
- * Set the state of treating developer (author) warnings as errors.
- */
- void SetDevWarningsAsErrors(bool v);
-
- /**
- * Get the state of treating deprecated warnings as errors.
- * Returns false, by default, if warnings should not be treated as errors,
- * true otherwise.
- */
- bool GetDeprecatedWarningsAsErrors() const;
- /**
- * Set the state of treating developer (author) warnings as errors.
- */
- void SetDeprecatedWarningsAsErrors(bool v);
-
/** Display a message to the user. */
void IssueMessage(
MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
+ void IssueDiagnostic(
+ cmDiagnosticCategory category, std::string const& text,
+ cmStateSnapshot const& state,
+ cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
+ void IssueDiagnostic(
+ cmDiagnosticCategory category, std::string const& text,
+ cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const
+ {
+ this->IssueDiagnostic(category, text, this->CurrentSnapshot, backtrace);
+ }
//! run the --build option
int Build(cmBuildArgs buildArgs, std::vector<std::string> targets,
@@ -767,7 +736,6 @@
void AddDefaultGenerators();
void AddDefaultExtraGenerators();
- std::map<std::string, DiagLevel> DiagLevels;
std::string GeneratorInstance;
std::string GeneratorPlatform;
std::string GeneratorToolset;
@@ -818,8 +786,6 @@
#ifndef CMAKE_BOOTSTRAP
std::unique_ptr<cmConfigureLog> ConfigureLog;
#endif
- bool WarnUninitialized = false;
- bool WarnUnusedCli = true;
bool CheckSystemVars = false;
bool IgnoreCompileWarningAsError = false;
bool IgnoreLinkWarningAsError = false;
@@ -917,7 +883,7 @@
void SetScriptModeExitCode(int code) { ScriptModeExitCode = code; }
int GetScriptModeExitCode() const { return ScriptModeExitCode.value_or(-1); }
- static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[19];
+ static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[15];
};
#define FOR_EACH_C90_FEATURE(F) F(c_function_prototypes)
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 35346af..7b325ee 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -73,7 +73,7 @@
"Run 'cmake --help' for more information."
};
-cmDocumentationEntry const cmDocumentationOptions[35] = {
+cmDocumentationEntry const cmDocumentationOptions[] = {
{ "--preset <preset>,--preset=<preset>", "Specify a configure preset." },
{ "--list-presets[=<type>]", "List available presets." },
{ "--workflow [<options>]", "Run a workflow preset." },
@@ -118,8 +118,6 @@
"Trace only this CMake file/module. Multiple options allowed." },
{ "--trace-redirect=<file>",
"Redirect trace output to a file instead of stderr." },
- { "--warn-uninitialized", "Warn about uninitialized values." },
- { "--no-warn-unused-cli", "Don't warn about command line options." },
{ "--check-system-vars",
"Find problems with variable usage in system files." },
{ "--compile-no-warning-as-error",
@@ -523,7 +521,8 @@
cmCommandLineArgument<bool(std::string const& value)>;
std::vector<CommandArgument> arguments = {
- CommandArgument{ "--preset", CommandArgument::Values::One,
+ CommandArgument{ "--preset", "No preset specified for --preset",
+ CommandArgument::Values::One,
CommandArgument::setToValue(presetName) },
CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
CommandArgument::setToTrue(listPresets) },
@@ -801,7 +800,7 @@
assert(1 < ac);
std::string config;
- std::string component;
+ std::vector<std::string> components;
std::string defaultDirectoryPermissions;
std::string prefix;
std::string dir;
@@ -809,6 +808,17 @@
bool strip = false;
bool verbose = cmSystemTools::HasEnv("VERBOSE");
+ auto componentLambda = [&components](std::string const& value) -> bool {
+ if (!value.empty()) {
+ cmList values{ value };
+ for (auto const& v : values) {
+ components.emplace_back(v);
+ }
+ return true;
+ }
+ return false;
+ };
+
auto jLambda = extract_job_number_lambda_builder(dir, jobs, "-j");
auto parallelLambda =
extract_job_number_lambda_builder(dir, jobs, "--parallel");
@@ -824,12 +834,13 @@
std::vector<CommandArgument> arguments = {
CommandArgument{ "--config", CommandArgument::Values::One,
CommandArgument::setToValue(config) },
- CommandArgument{ "--component", CommandArgument::Values::One,
- CommandArgument::setToValue(component) },
+ CommandArgument{ "--component", CommandArgument::Values::OneOrMore,
+ componentLambda },
CommandArgument{
"--default-directory-permissions", CommandArgument::Values::One,
CommandArgument::setToValue(defaultDirectoryPermissions) },
- CommandArgument{ "-j", CommandArgument::Values::One, jLambda },
+ CommandArgument{ "-j", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, jLambda },
CommandArgument{ "--parallel", CommandArgument::Values::One,
parallelLambda },
CommandArgument{ "--prefix", CommandArgument::Values::One,
@@ -876,6 +887,7 @@
" <dir> = Project binary directory to install.\n"
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n"
" --component <comp> = Component-based install. Only install <comp>.\n"
+ " May be passed multiple components. t\n"
" --default-directory-permissions <permission> \n"
" Default install permission. Use default permission <permission>.\n"
" -j <jobs> --parallel <jobs>\n"
@@ -896,10 +908,6 @@
args.emplace_back("-DCMAKE_INSTALL_PREFIX=" + prefix);
}
- if (!component.empty()) {
- args.emplace_back("-DCMAKE_INSTALL_COMPONENT=" + component);
- }
-
if (strip) {
args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1");
}
@@ -919,7 +927,7 @@
args.emplace_back("-P");
cmInstrumentation instrumentation(dir);
- auto handler = cmInstallScriptHandler(dir, component, config, args);
+ auto handler = cmInstallScriptHandler(dir, components, config, args);
int ret = 0;
if (!jobs && handler.IsParallel()) {
jobs = 1;
@@ -982,7 +990,8 @@
cmCommandLineArgument<bool(std::string const& value)>;
std::vector<CommandArgument> arguments = {
- CommandArgument{ "--preset", CommandArgument::Values::One,
+ CommandArgument{ "--preset", "No preset specified for --preset",
+ CommandArgument::Values::One,
CommandArgument::setToValue(presetName) },
CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
[&listPresets](std::string const&) -> bool {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 7d95c73..6610da0 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -17,6 +17,7 @@
#include "cmCommandLineArgument.h"
#include "cmCryptoHash.h"
#include "cmDuration.h"
+#include "cmEnvironment.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
@@ -105,13 +106,19 @@
cat [--] <files>... - concat the files and print them to the standard output
chdir dir cmd [args...] - run command in a given directory
compare_files [--ignore-eol] file1 file2
- - check if file1 is same as file2
- copy <file>... destination - copy files to destination (either file or directory)
- copy_directory <dir>... destination - copy content of <dir>... directories to 'destination' directory
- copy_directory_if_different <dir>... destination - copy changed content of <dir>... directories to 'destination' directory
- copy_directory_if_newer <dir>... destination - copy newer content of <dir>... directories to 'destination' directory
- copy_if_different <file>... destination - copy files if it has changed
- copy_if_newer <file>... destination - copy files if source is newer than destination
+ - check if file1 is same as file2
+ copy <file>... destination | -t <destination> <file>...
+ - copy files to destination (either file or directory)
+ copy_directory <dir>... destination | -t <destination> <dir>...
+ - copy content of <dir>... directories to 'destination' directory
+ copy_directory_if_different <dir>... destination | -t <destination> <dir>...
+ - copy changed content of <dir>... directories to 'destination' directory
+ copy_directory_if_newer <dir>... destination | -t <destination> <dir>...
+ - copy newer content of <dir>... directories to 'destination' directory
+ copy_if_different <file>... destination | -t <destination> <file>...
+ - copy files if source has changed
+ copy_if_newer <file>... destination | -t <destination> <file>...
+ - copy files if source is newer than destination
echo [<string>...] - displays arguments as text
echo_append [<string>...] - displays arguments as text but no new line
env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]
@@ -203,7 +210,7 @@
return true;
}
-void cmCatFile(std::string const& fileToAppend)
+void cmCatFile(cm::optional<std::string> fileToAppend)
{
#ifdef _WIN32
_setmode(fileno(stdin), _O_BINARY);
@@ -211,8 +218,8 @@
#endif
std::streambuf* buf = std::cin.rdbuf();
cmsys::ifstream source;
- if (fileToAppend != "-") {
- source.open(fileToAppend.c_str(), (std::ios::binary | std::ios::in));
+ if (fileToAppend.has_value()) {
+ source.open(fileToAppend->c_str(), (std::ios::binary | std::ios::in));
buf = source.rdbuf();
}
std::cout << buf;
@@ -632,13 +639,16 @@
// Create the default manifest ruleset file when not found
if (!cmSystemTools::FileExists("cstat_sel_checks.txt")) {
- std::string ichecks_cmd = cmSystemTools::GetFilenamePath(orig_cmd[0]);
- ichecks_cmd = cmStrCat(ichecks_cmd, "/ichecks --default stdchecks");
+ std::vector<std::string> ichecks_cmd;
+ ichecks_cmd.emplace_back(
+ cmStrCat(cmSystemTools::GetFilenamePath(orig_cmd[0]), "/ichecks"));
+ ichecks_cmd.emplace_back("--default");
+ ichecks_cmd.emplace_back("stdchecks");
if (!cmSystemTools::RunSingleCommand(ichecks_cmd, &stdOut, &stdErr, &ret,
nullptr,
cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error generating default manifest file '" << ichecks_cmd
- << "'. " << stdOut << '\n';
+ std::cerr << "Error generating default manifest file '" << ichecks_cmd[0]
+ << "': " << stdOut << '\n';
return 1;
}
}
@@ -1002,8 +1012,26 @@
{
// IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
if (args.size() > 1) {
- // Copy file
- if (args[1] == "copy" && args.size() > 3) {
+ // Copy file, copy file if different, copy file if newer.
+ if ((args[1] == "copy" || args[1] == "copy_if_different" ||
+ args[1] == "copy_if_newer") &&
+ args.size() > 3) {
+ using CopyFn = cmsys::SystemTools::CopyStatus (*)(std::string const&,
+ std::string const&);
+ CopyFn copyFn;
+ std::string copyErrPrefix;
+ if (args[1] == "copy") {
+ copyFn = cmSystemTools::CopyFileAlways;
+ copyErrPrefix = "Error copying file";
+ } else if (args[1] == "copy_if_different") {
+ copyFn = cmSystemTools::CopyFileIfDifferent;
+ copyErrPrefix = "Error copying file (if different) from";
+ } else {
+ copyFn = cmSystemTools::CopyFileIfNewer;
+ copyErrPrefix = "Error copying file (if newer) from";
+ }
+ std::string const& cmdName = args[1];
+
using CommandArgument =
cmCommandLineArgument<bool(std::string const& value)>;
@@ -1038,14 +1066,14 @@
files.pop_back();
}
if (targetArg && (!cmSystemTools::FileIsDirectory(*targetArg))) {
- std::cerr << "Error: Target (for copy command) \"" << *targetArg
- << "\" is not a directory.\n";
+ std::cerr << "Error: Target (for " << cmdName << " command) \""
+ << *targetArg << "\" is not a directory.\n";
return 1;
}
if (!targetArg) {
if (files.size() < 2) {
- std::cerr
- << "Error: No files or target specified (for copy command).\n";
+ std::cerr << "Error: No files or target specified (for " << cmdName
+ << " command).\n";
return 1;
}
targetArg = files.back();
@@ -1054,10 +1082,9 @@
// If error occurs we want to continue copying next files.
bool return_value = false;
for (auto const& file : files) {
- cmsys::SystemTools::CopyStatus const status =
- cmSystemTools::CopyFileAlways(file, *targetArg);
+ cmsys::SystemTools::CopyStatus const status = copyFn(file, *targetArg);
if (!status) {
- std::cerr << "Error copying file \"" << file << "\" to \""
+ std::cerr << copyErrPrefix << " \"" << file << "\" to \""
<< *targetArg << "\": " << status.GetString() << '\n';
return_value = true;
}
@@ -1065,77 +1092,68 @@
return return_value;
}
- // Copy file if different.
- if (args[1] == "copy_if_different" && args.size() > 3) {
- // If multiple source files specified,
- // then destination must be directory
- if ((args.size() > 4) &&
- (!cmSystemTools::FileIsDirectory(args.back()))) {
- std::cerr << "Error: Target (for copy_if_different command) \""
- << args.back() << "\" is not a directory.\n";
- return 1;
- }
- // If error occurs we want to continue copying next files.
- bool return_value = false;
- for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
- cmsys::SystemTools::CopyStatus const status =
- cmSystemTools::CopyFileIfDifferent(arg, args.back());
- if (!status) {
- std::cerr << "Error copying file (if different) from \"" << arg
- << "\" to \"" << args.back()
- << "\": " << status.GetString() << '\n';
- return_value = true;
- }
- }
- return return_value;
- }
-
- // Copy file if newer.
- if (args[1] == "copy_if_newer" && args.size() > 3) {
- // If multiple source files specified,
- // then destination must be directory
- if ((args.size() > 4) &&
- (!cmSystemTools::FileIsDirectory(args.back()))) {
- std::cerr << "Error: Target (for copy_if_newer command) \""
- << args.back() << "\" is not a directory.\n";
- return 1;
- }
- // If error occurs we want to continue copying next files.
- bool return_value = false;
- for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
- cmsys::SystemTools::CopyStatus const status =
- cmSystemTools::CopyFileIfNewer(arg, args.back());
- if (!status) {
- std::cerr << "Error copying file (if newer) from \"" << arg
- << "\" to \"" << args.back()
- << "\": " << status.GetString() << '\n';
- return_value = true;
- }
- }
- return return_value;
- }
-
// Copy directory contents
- if ((args[1] == "copy_directory" ||
- args[1] == "copy_directory_if_different" ||
- args[1] == "copy_directory_if_newer") &&
- args.size() > 3) {
- // If error occurs we want to continue copying next files.
- bool return_value = false;
-
+ if (args[1] == "copy_directory" ||
+ args[1] == "copy_directory_if_different" ||
+ args[1] == "copy_directory_if_newer") {
cmsys::SystemTools::CopyWhen when = cmsys::SystemTools::CopyWhen::Always;
if (args[1] == "copy_directory_if_different") {
when = cmsys::SystemTools::CopyWhen::OnlyIfDifferent;
} else if (args[1] == "copy_directory_if_newer") {
when = cmsys::SystemTools::CopyWhen::OnlyIfNewer;
}
+ std::string const& cmdName = args[1];
- for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ using CommandArgument =
+ cmCommandLineArgument<bool(std::string const& value)>;
+
+ cm::optional<std::string> targetArg;
+ std::vector<CommandArgument> argParsers{
+ { "-t", CommandArgument::Values::One,
+ CommandArgument::setToValue(targetArg) },
+ };
+
+ std::vector<std::string> dirs;
+ for (decltype(args.size()) i = 2; i < args.size(); i++) {
+ std::string const& arg = args[i];
+ bool matched = false;
+ for (auto const& m : argParsers) {
+ if (m.matches(arg)) {
+ matched = true;
+ if (m.parse(arg, i, args)) {
+ break;
+ }
+ return 1; // failed to parse
+ }
+ }
+ if (!matched) {
+ dirs.push_back(arg);
+ }
+ }
+
+ if (!targetArg) {
+ if (dirs.size() < 2) {
+ std::cerr << "Error: No directories or target specified (for "
+ << cmdName << " command).\n";
+ return 1;
+ }
+ targetArg = dirs.back();
+ dirs.pop_back();
+ }
+ if (dirs.empty()) {
+ std::cerr << "Error: No source directories specified (for " << cmdName
+ << " command).\n";
+ return 1;
+ }
+
+ // If error occurs we want to continue copying next files.
+ bool return_value = false;
+ for (auto const& dir : dirs) {
cmsys::Status const status =
- cmSystemTools::CopyADirectory(arg, args.back(), when);
+ cmSystemTools::CopyADirectory(dir, *targetArg, when);
if (!status) {
- std::cerr << "Error copying directory from \"" << arg << "\" to \""
- << args.back() << "\": " << status.GetString() << '\n';
+ std::cerr << "Error copying directory from \"" << dir << "\" to \""
+ << *targetArg << "\": " << status.GetString() << '\n';
return_value = true;
}
}
@@ -1250,7 +1268,7 @@
if (args[1] == "env") {
#ifndef CMAKE_BOOTSTRAP
- cmSystemTools::EnvDiff env;
+ auto envdiff = cmEnvironmentModification{};
#endif
auto ai = args.cbegin() + 2;
@@ -1268,7 +1286,7 @@
#ifdef CMAKE_BOOTSTRAP
cmSystemTools::UnPutEnv(a.substr(8));
#else
- env.UnPutEnv(a.substr(8));
+ envdiff.Add(a.substr(8) + "=unset:");
#endif
} else if (a == "--modify") {
#ifdef CMAKE_BOOTSTRAP
@@ -1281,7 +1299,7 @@
return 1;
}
std::string const& op = *ai;
- if (!env.ParseOperation(op)) {
+ if (!envdiff.Add(op)) {
std::cerr << "cmake -E env: invalid parameter to --modify: " << op
<< '\n';
return 1;
@@ -1297,7 +1315,10 @@
#ifdef CMAKE_BOOTSTRAP
cmSystemTools::PutEnv(a);
#else
- env.PutEnv(a);
+ auto const pos = a.find('=');
+ std::string const& name = a.substr(0, pos);
+ std::string const& value = a.substr(pos + 1);
+ envdiff.Add(cmStrCat(name, "=set:", value));
#endif
} else {
// This is the beginning of the command.
@@ -1310,16 +1331,19 @@
return 1;
}
+ auto env = cmEnvironment{};
#ifndef CMAKE_BOOTSTRAP
- env.ApplyToCurrentEnv();
+ env.Update(cmSystemTools::GetEnvironmentVariables());
+ envdiff.ApplyTo(env);
#endif
// Execute command from remaining arguments.
std::vector<std::string> cmd(ai, ae);
int retval;
- if (cmSystemTools::RunSingleCommand(cmd, nullptr, nullptr, &retval,
- nullptr,
- cmSystemTools::OUTPUT_PASSTHROUGH)) {
+ if (cmSystemTools::RunSingleCommand(
+ cmd, nullptr, nullptr, &retval, nullptr,
+ cmSystemTools::OUTPUT_PASSTHROUGH, cmDuration::zero(),
+ cmProcessOutput::Auto, env.GetVariables())) {
return retval;
}
return 1;
@@ -1535,7 +1559,13 @@
}
// Command to concat files into one
- if (args[1] == "cat" && args.size() >= 3) {
+ if (args[1] == "cat") {
+ if (args.size() == 2) {
+ // Destroy console buffers to drop cout/cerr encoding transform.
+ console.reset();
+ cmCatFile(cm::nullopt);
+ return 0;
+ }
int return_value = 0;
bool doing_options = true;
for (auto const& arg : cmMakeRange(args).advance(2)) {
@@ -1543,7 +1573,7 @@
doing_options = false;
// Destroy console buffers to drop cout/cerr encoding transform.
console.reset();
- cmCatFile(arg);
+ cmCatFile(cm::nullopt);
} else if (doing_options && cmHasPrefix(arg, '-')) {
if (arg == "--") {
doing_options = false;
@@ -1897,6 +1927,7 @@
cmSystemTools::TarCompressAuto;
int nCompress = 0;
bool doing_options = true;
+ std::string encoding = "UTF-8";
for (auto const& arg : cmMakeRange(args).advance(4)) {
if (doing_options && cmHasLiteralPrefix(arg, "--")) {
if (arg == "--") {
@@ -1934,6 +1965,13 @@
}
numThreads = static_cast<decltype(numThreads)>(numThreadsLong);
+ } else if (cmHasLiteralPrefix(arg, "--cmake-tar-encoding=")) {
+ encoding = arg.substr(21);
+ if (encoding.empty()) {
+ cmSystemTools::Error(
+ "Encoding value is empty - it must be filled if passed");
+ return 1;
+ }
} else if (cmHasLiteralPrefix(arg,
"--cmake-tar-compression-level=")) {
std::string const& compressionLevelStr = arg.substr(30);
@@ -2083,7 +2121,7 @@
}
if (action == cmSystemTools::TarActionList) {
- if (!cmSystemTools::ListTar(outFile, files, verbose)) {
+ if (!cmSystemTools::ListTar(outFile, files, encoding, verbose)) {
cmSystemTools::Error("Problem listing tar: " + outFile);
return 1;
}
@@ -2091,15 +2129,15 @@
if (files.empty()) {
std::cerr << "tar: No files or directories specified\n";
}
- if (!cmSystemTools::CreateTar(outFile, files, {}, compress, verbose,
- mtime, format, compressionLevel,
+ if (!cmSystemTools::CreateTar(outFile, files, {}, compress, encoding,
+ verbose, mtime, format, compressionLevel,
numThreads)) {
cmSystemTools::Error(cmStrCat("Problem creating tar:\n ", outFile));
return 1;
}
} else if (action == cmSystemTools::TarActionExtract) {
if (!cmSystemTools::ExtractTar(outFile, files, extractTimestamps,
- verbose)) {
+ encoding, verbose)) {
cmSystemTools::Error(
cmStrCat("Problem extracting tar:\n ", outFile));
return 1;
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index fbfd978..fc8e5a3 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -209,12 +209,13 @@
return 1;
}
+ bool const haveTestfile = cmSystemTools::FileExists("CTestTestfile.cmake") ||
+ cmSystemTools::FileExists("DartTestfile.txt");
+
// If there is a testing input file, check for documentation options
// only if there are actually arguments. We want running without
// arguments to run tests.
- if (argc > 1 ||
- !(cmSystemTools::FileExists("CTestTestfile.cmake") ||
- cmSystemTools::FileExists("DartTestfile.txt"))) {
+ if (argc > 1 || !haveTestfile) {
if (argc == 1) {
std::cerr << "*********************************\n"
"No test configuration file found!\n"
@@ -228,7 +229,8 @@
doc.SetSection("Name", cmDocumentationName);
doc.SetSection("Usage", cmDocumentationUsage);
doc.PrependSection("Options", cmDocumentationOptions);
- return !doc.PrintRequestedDocumentation(std::cout);
+ return !doc.PrintRequestedDocumentation(std::cout) ||
+ (argc == 1 && !haveTestfile);
}
}
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index be312cc..cde43ca 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -242,7 +242,7 @@
break;
default:
std::cerr << "Got unknown argument type: \"" << cs->ArgumentType
- << "\"" << std::endl;
+ << '"' << std::endl;
this->Internals->LastArgument--;
return 0;
}
@@ -259,7 +259,7 @@
CommandLineArguments_DEBUG("Store unused argument " << arg);
this->Internals->UnusedArguments.push_back(arg);
} else {
- std::cerr << "Got unknown argument: \"" << arg << "\"" << std::endl;
+ std::cerr << "Got unknown argument: \"" << arg << '"' << std::endl;
this->Internals->LastArgument--;
return 0;
}
@@ -566,7 +566,7 @@
}
if (cnt > 0) {
for (cc = 0; cc < maxlen; cc++) {
- str << " ";
+ str << ' ';
}
}
CommandLineArguments::Internal::String::size_type skip = len;
@@ -751,8 +751,8 @@
static_cast<std::vector<std::string>*>(cs->Variable), var);
break;
default:
- std::cerr << "Got unknown variable type: \"" << cs->VariableType
- << "\"" << std::endl;
+ std::cerr << "Got unknown variable type: \"" << cs->VariableType << '"'
+ << std::endl;
this->Internals->LastArgument--;
return false;
}
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
index 885a1f7..1d1eed8 100644
--- a/Source/kwsys/EncodingCXX.cxx
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -19,6 +19,7 @@
# include "String.h"
#endif
+#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <vector>
@@ -131,13 +132,10 @@
MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
int(str.size()), nullptr, 0);
if (wlength > 0) {
- wchar_t* wdata = new wchar_t[wlength];
+ wstr.resize(wlength);
int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
- int(str.size()), wdata, wlength);
- if (r > 0) {
- wstr = std::wstring(wdata, wlength);
- }
- delete[] wdata;
+ int(str.size()), &wstr[0], wlength);
+ wstr.resize(static_cast<size_t>((std::max)(0, r)));
}
#else
size_t pos = 0;
@@ -164,14 +162,11 @@
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
int(str.size()), nullptr, 0, nullptr, nullptr);
if (length > 0) {
- char* data = new char[length];
+ nstr.resize(length);
int r =
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
- int(str.size()), data, length, nullptr, nullptr);
- if (r > 0) {
- nstr = std::string(data, length);
- }
- delete[] data;
+ int(str.size()), &nstr[0], length, nullptr, nullptr);
+ nstr.resize(static_cast<size_t>((std::max)(0, r)));
}
#else
size_t pos = 0;
@@ -198,10 +193,9 @@
return wstr;
}
++length;
- std::vector<wchar_t> wchars(length);
- if (kwsysEncoding_mbstowcs(wchars.data(), cstr, length) > 0) {
- wstr = wchars.data();
- }
+ wstr.resize(length);
+ length = kwsysEncoding_mbstowcs(&wstr[0], cstr, length);
+ wstr.resize(length);
return wstr;
}
@@ -213,45 +207,78 @@
return str;
}
++length;
- std::vector<char> chars(length);
- if (kwsysEncoding_wcstombs(chars.data(), wcstr, length) > 0) {
- str = chars.data();
- }
+ str.resize(length);
+ length = kwsysEncoding_wcstombs(&str[0], wcstr, length);
+ str.resize(length);
return str;
}
#if defined(_WIN32)
-// Convert local paths to UNC style paths
+// Convert local paths to UNC style paths:
+// * https://web.archive.org/web/20250329050419/
+// https://cpp.arsenmk.com/2015/12/handling-long-paths-on-windows.html
+
+namespace {
+// UNC prefix for local paths.
+std::wstring const unc_local_prefix = L"\\\\?\\";
+
+// UNC prefix for remote paths.
+std::wstring const unc_remote_prefix = L"\\\\?\\UNC\\";
+
+// The longest UNC prefix replaces two leading backslashes.
+size_t const unc_max_space = unc_remote_prefix.length() - 2;
+}
+
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
return ToWindowsExtendedPath(ToWide(source));
}
-// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(char const* source)
{
return ToWindowsExtendedPath(ToWide(source));
}
-// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::wstring const& wsource)
{
// Resolve any relative paths
+ std::wstring wfull;
DWORD wfull_len;
- /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
- * won't return a large enough buffer size if the input is too small */
- wfull_len = GetFullPathNameW(wsource.c_str(), 0, nullptr, nullptr) + 3;
- std::vector<wchar_t> wfull(wfull_len);
- GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], nullptr);
+ // Try with a stack-allocated buffer first.
+ wchar_t local_buf[512];
+ size_t const local_buf_len = sizeof(local_buf) / sizeof(local_buf[0]);
+ wfull_len =
+ GetFullPathNameW(wsource.c_str(), local_buf_len, local_buf, nullptr);
+ if (wfull_len <= local_buf_len) {
+ // The stack-allocated buffer was large enough. It holds the result.
- /* This should get the correct size without any extra padding from the
- * previous size workaround. */
- wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));
+ // Reserve room for the prefix added below.
+ wfull.reserve(wfull_len + unc_max_space);
+
+ // Store the absolute path to be returned.
+ wfull.assign(local_buf, wfull_len);
+ } else {
+ // The stack-allocated buffer was too small, but now we know how
+ // much to allocate on the heap.
+
+ // Some versions of GetFullPathNameW return a slightly too-small size.
+ wfull_len += 3;
+
+ // Reserve room for the prefix added below.
+ wfull.reserve(wfull_len + unc_max_space);
+
+ // Try again with a heap-allocated buffer.
+ wfull.resize(wfull_len, L'\0');
+ wfull_len =
+ GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], nullptr);
+ wfull.resize(wfull_len);
+ }
if (wfull_len >= 2 && kwsysString_isalpha(wfull[0]) &&
wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
- return L"\\\\?\\" + std::wstring(&wfull[0]);
+ wfull.insert(0, unc_local_prefix);
+ return wfull;
} else if (wfull_len >= 2 && wfull[0] == L'\\' &&
wfull[1] == L'\\') { /* Starts with \\ */
if (wfull_len >= 4 && wfull[2] == L'?' &&
@@ -259,24 +286,27 @@
if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
wfull[6] == L'C' &&
wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
- return std::wstring(&wfull[0]);
+ return wfull;
} else if (wfull_len >= 6 && kwsysString_isalpha(wfull[4]) &&
wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
- return std::wstring(&wfull[0]);
+ return wfull;
} else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
- return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
+ wfull.replace(0, 4, unc_remote_prefix);
+ return wfull;
}
} else if (wfull_len >= 4 && wfull[2] == L'.' &&
wfull[3] == L'\\') { /* Starts with \\.\ a device name */
if (wfull_len >= 6 && kwsysString_isalpha(wfull[4]) &&
wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
- return L"\\\\?\\" + std::wstring(&wfull[4]);
+ wfull.replace(0, 4, unc_local_prefix);
+ return wfull;
} else if (wfull_len >=
5) { /* \\.\Foo\bar\ Device name is left unchanged */
- return std::wstring(&wfull[0]);
+ return wfull;
}
} else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
- return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
+ wfull.replace(0, 2, unc_remote_prefix);
+ return wfull;
}
}
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index d6d6f84..25c2d33 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -28,15 +28,13 @@
template <typename CharType, typename Traits>
class basic_filebuf : public std::basic_filebuf<CharType, Traits>
{
-# if _MSC_VER >= 1400
public:
typedef std::basic_filebuf<CharType, Traits> my_base_type;
- basic_filebuf* open(char const* s, std::ios_base::openmode mode)
+ basic_filebuf* open(std::string const& s, std::ios_base::openmode mode)
{
std::wstring const wstr = Encoding::ToWindowsExtendedPath(s);
- return static_cast<basic_filebuf*>(my_base_type::open(wstr.c_str(), mode));
+ return static_cast<basic_filebuf*>(my_base_type::open(wstr, mode));
}
-# endif
};
# else
@@ -46,23 +44,23 @@
std::wstring cmode;
bool plus = false;
if (mode & std::ios_base::app) {
- cmode += L"a";
+ cmode += L'a';
plus = mode & std::ios_base::in ? true : false;
} else if (mode & std::ios_base::trunc ||
(mode & std::ios_base::out && (mode & std::ios_base::in) == 0)) {
- cmode += L"w";
+ cmode += L'w';
plus = mode & std::ios_base::in ? true : false;
} else {
- cmode += L"r";
+ cmode += L'r';
plus = mode & std::ios_base::out ? true : false;
}
if (plus) {
- cmode += L"+";
+ cmode += L'+';
}
if (mode & std::ios_base::binary) {
- cmode += L"b";
+ cmode += L'b';
} else {
- cmode += L"t";
+ cmode += L't';
}
return cmode;
};
@@ -85,7 +83,7 @@
buf_ = 0;
}
- bool _open(char const* file_name, std::ios_base::openmode mode)
+ bool _open(std::string const& file_name, std::ios_base::openmode mode)
{
if (_is_open() || file_) {
return false;
@@ -182,7 +180,7 @@
this->buf_ =
static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
}
- explicit basic_fstream(char const* file_name,
+ explicit basic_fstream(std::string const& file_name,
std::ios_base::openmode mode = std::ios_base::in |
std::ios_base::out)
: internal_stream_type(new internal_buffer_type())
@@ -192,7 +190,7 @@
open(file_name, mode);
}
- void open(char const* file_name,
+ void open(std::string const& file_name,
std::ios_base::openmode mode = std::ios_base::in |
std::ios_base::out)
{
@@ -226,7 +224,7 @@
this->buf_ =
static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
}
- explicit basic_ifstream(char const* file_name,
+ explicit basic_ifstream(std::string const& file_name,
std::ios_base::openmode mode = std::ios_base::in)
: internal_stream_type(new internal_buffer_type())
{
@@ -235,7 +233,7 @@
open(file_name, mode);
}
- void open(char const* file_name,
+ void open(std::string const& file_name,
std::ios_base::openmode mode = std::ios_base::in)
{
mode = mode | std::ios_base::in;
@@ -271,7 +269,7 @@
this->buf_ =
static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
}
- explicit basic_ofstream(char const* file_name,
+ explicit basic_ofstream(std::string const& file_name,
std::ios_base::openmode mode = std::ios_base::out)
: internal_stream_type(new internal_buffer_type())
{
@@ -279,7 +277,7 @@
static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
open(file_name, mode);
}
- void open(char const* file_name,
+ void open(std::string const& file_name,
std::ios_base::openmode mode = std::ios_base::out)
{
mode = mode | std::ios_base::out;
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 3ac75f6..9d48bc2 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -125,11 +125,11 @@
std::string::const_iterator k = bracket_first;
// Open the regex block.
- regex += "[";
+ regex += '[';
// A regex range complement uses '^' instead of '!'.
if (k != bracket_last && *k == '!') {
- regex += "^";
+ regex += '^';
++k;
}
@@ -137,7 +137,7 @@
for (; k != bracket_last; ++k) {
// Backslashes must be escaped.
if (*k == '\\') {
- regex += "\\";
+ regex += '\\';
}
// Store this character.
@@ -145,7 +145,7 @@
}
// Close the regex block.
- regex += "]";
+ regex += ']';
// Jump to the end of the bracket string.
i = bracket_last;
@@ -156,7 +156,7 @@
if (!(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9'))) {
// Escape the non-alphanumeric character.
- regex += "\\";
+ regex += '\\';
}
#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
else {
@@ -174,7 +174,7 @@
}
if (require_whole_string) {
- regex += "$";
+ regex += '$';
}
return regex;
}
@@ -189,7 +189,7 @@
if (!errorMessage.empty()) {
messages->push_back(Message(Glob::warning,
"Error listing directory '" + dir +
- "'! Reason: '" + errorMessage + "'"));
+ "'! Reason: '" + errorMessage + '\''));
}
}
return true;
@@ -198,7 +198,7 @@
std::string realname;
std::string fname;
for (cc = 0; cc < d.GetNumberOfFiles(); cc++) {
- fname = d.GetFile(cc);
+ fname = d.GetFileName(cc);
if (fname == "." || fname == "..") {
continue;
}
@@ -206,7 +206,7 @@
if (start == 0) {
realname = dir + fname;
} else {
- realname = dir + "/" + fname;
+ realname = dir + '/' + fname;
}
#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
@@ -229,7 +229,7 @@
messages->push_back(
Message(Glob::error,
"Canonical path generation from path '" + dir +
- "' failed! Reason: '" + realPathErrorMessage + "'"));
+ "' failed! Reason: '" + realPathErrorMessage + '\''));
}
return false;
}
@@ -257,9 +257,9 @@
std::find(this->VisitedSymlinks.begin(),
this->VisitedSymlinks.end(), canonicalPath);
pathIt != this->VisitedSymlinks.end(); ++pathIt) {
- message += *pathIt + "\n";
+ message += *pathIt + '\n';
}
- message += canonicalPath + "/" + fname;
+ message += canonicalPath + '/' + fname;
messages->push_back(Message(Glob::cyclicRecursion, message));
}
} else {
@@ -305,7 +305,7 @@
std::string realname;
std::string fname;
for (cc = 0; cc < d.GetNumberOfFiles(); cc++) {
- fname = d.GetFile(cc);
+ fname = d.GetFileName(cc);
if (fname == "." || fname == "..") {
continue;
}
@@ -313,7 +313,7 @@
if (start == 0) {
realname = dir + fname;
} else {
- realname = dir + "/" + fname;
+ realname = dir + '/' + fname;
}
#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
@@ -353,7 +353,8 @@
if (!kwsys::SystemTools::FileIsFullPath(expr)) {
expr = kwsys::SystemTools::GetCurrentWorkingDirectory();
- expr += "/" + inexpr;
+ expr += '/';
+ expr += inexpr;
}
std::string fexpr = expr;
@@ -416,7 +417,7 @@
// Handle network paths
if (skip > 0) {
- this->ProcessDirectory(0, fexpr.substr(0, skip) + "/", messages);
+ this->ProcessDirectory(0, fexpr.substr(0, skip) + '/', messages);
} else {
this->ProcessDirectory(0, "/", messages);
}
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 0a472d3..80766dd 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -602,7 +602,7 @@
oss << this->GetNumberOfPhysicalCPU() << " core ";
if (this->GetModelName().empty()) {
oss << this->GetProcessorClockFrequency() << " MHz "
- << this->GetVendorString() << " " << this->GetExtendedProcessorName();
+ << this->GetVendorString() << ' ' << this->GetExtendedProcessorName();
} else {
oss << this->GetModelName();
}
@@ -679,7 +679,7 @@
std::string SystemInformation::GetOSDescription()
{
std::ostringstream oss;
- oss << this->GetOSName() << " " << this->GetOSRelease() << " "
+ oss << this->GetOSName() << ' ' << this->GetOSRelease() << ' '
<< this->GetOSVersion();
return oss.str();
@@ -961,7 +961,7 @@
oss << std::endl
<< "========================================================="
<< std::endl
- << "Process id " << getpid() << " ";
+ << "Process id " << getpid() << ' ';
switch (sigNo) {
case SIGINT:
oss << "Caught SIGINT";
@@ -977,7 +977,7 @@
case SIGFPE:
oss << "Caught SIGFPE at " << (sigInfo->si_addr ? "" : "0x")
- << sigInfo->si_addr << " ";
+ << sigInfo->si_addr << ' ';
switch (sigInfo->si_code) {
# if defined(FPE_INTDIV)
case FPE_INTDIV:
@@ -1025,7 +1025,7 @@
case SIGSEGV:
oss << "Caught SIGSEGV at " << (sigInfo->si_addr ? "" : "0x")
- << sigInfo->si_addr << " ";
+ << sigInfo->si_addr << ' ';
switch (sigInfo->si_code) {
case SEGV_MAPERR:
oss << "address not mapped to object";
@@ -1043,7 +1043,7 @@
case SIGBUS:
oss << "Caught SIGBUS at " << (sigInfo->si_addr ? "" : "0x")
- << sigInfo->si_addr << " ";
+ << sigInfo->si_addr << ' ';
switch (sigInfo->si_code) {
case BUS_ADRALN:
oss << "invalid address alignment";
@@ -1083,7 +1083,7 @@
case SIGILL:
oss << "Caught SIGILL at " << (sigInfo->si_addr ? "" : "0x")
- << sigInfo->si_addr << " ";
+ << sigInfo->si_addr << ' ';
switch (sigInfo->si_code) {
case ILL_ILLOPC:
oss << "illegal opcode";
@@ -1248,8 +1248,8 @@
{
# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
os << std::hex << sp.GetAddress() << " : " << sp.GetFunction() << " [("
- << sp.GetBinary() << ") " << sp.GetSourceFile() << ":" << std::dec
- << sp.GetLineNumber() << "]";
+ << sp.GetBinary() << ") " << sp.GetSourceFile() << ':' << std::dec
+ << sp.GetLineNumber() << ']';
# elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
void* addr = sp.GetAddress();
char** syminfo = backtrace_symbols(&addr, 1);
@@ -3601,7 +3601,7 @@
std::string cpuflags = this->ExtractValueFromCpuInfoFile(buffer, "flags");
if (!cpurev.empty()) {
// now we can match every flags as space + flag + space
- cpuflags = " " + cpuflags + " ";
+ cpuflags = ' ' + cpuflags + ' ';
if ((cpuflags.find(" fpu ") != std::string::npos)) {
this->Features.HasFPU = true;
}
@@ -5068,7 +5068,7 @@
size_t pos = buffer.find("System RAM:");
if (pos == std::string::npos)
return false;
- pos = buffer.find(":", pos);
+ pos = buffer.find(':', pos);
size_t pos2 = buffer.find("M (", pos);
if (pos2 == std::string::npos)
return false;
@@ -5141,7 +5141,7 @@
pos2 = buffer.find(" Stepping", pos);
if (pos2 != std::string::npos) {
- pos2 = buffer.find(" ", pos2 + 1);
+ pos2 = buffer.find(' ', pos2 + 1);
if (pos2 != std::string::npos && pos2 < pos3) {
this->ChipID.Revision =
atoi(buffer.substr(pos2 + 1, pos3 - pos2).c_str());
@@ -5354,8 +5354,8 @@
# endif
// Produce the release like it is displayed in `cmd`
- this->OSRelease = std::to_string(osvi.dwMajorVersion) + "." +
- std::to_string(osvi.dwMinorVersion) + "." +
+ this->OSRelease = std::to_string(osvi.dwMajorVersion) + '.' +
+ std::to_string(osvi.dwMinorVersion) + '.' +
std::to_string(osvi.dwBuildNumber & 0xFFFF);
struct VersionNames
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 7e23c16..073bb64 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -563,7 +563,7 @@
// actual case of servers and shares.
if (path_components.size() > 2 && path_components[0] == "//") {
casePath += path_components[idx++];
- casePath += "/";
+ casePath += '/';
casePath += path_components[idx++];
sep = "/";
}
@@ -2053,7 +2053,7 @@
static void ConvertVMSToUnix(std::string& path)
{
std::string::size_type rootEnd = path.find(":[");
- std::string::size_type pathEnd = path.find("]");
+ std::string::size_type pathEnd = path.find(']');
if (rootEnd != std::string::npos) {
std::string root = path.substr(0, rootEnd);
std::string pathPart = path.substr(rootEnd + 2, pathEnd - rootEnd - 2);
@@ -2065,7 +2065,7 @@
}
pos0++;
}
- path = "/" + root + "/" + pathPart;
+ path = '/' + root + '/' + pathPart;
}
}
#endif
@@ -2660,15 +2660,15 @@
}
for (size_t fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
- if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
- strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) {
+ std::string const& filename = dir.GetFileName(fileNum);
+ if (filename != "." && filename != "..") {
std::string fullPath = source;
- fullPath += "/";
- fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+ fullPath += '/';
+ fullPath += filename;
if (SystemTools::FileIsDirectory(fullPath)) {
std::string fullDestPath = destination;
- fullDestPath += "/";
- fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+ fullDestPath += '/';
+ fullDestPath += filename;
status = SystemTools::CopyADirectory(fullPath, fullDestPath, when);
if (!status.IsSuccess()) {
return status;
@@ -2841,11 +2841,11 @@
size_t fileNum;
for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
- if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
- strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) {
+ std::string const& filename = dir.GetFileName(fileNum);
+ if (filename != "." && filename != "..") {
std::string fullPath = source;
- fullPath += "/";
- fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+ fullPath += '/';
+ fullPath += filename;
if (SystemTools::FileIsDirectory(fullPath) &&
!SystemTools::FileIsSymlink(fullPath)) {
status = SystemTools::RemoveADirectory(fullPath);
@@ -3035,9 +3035,13 @@
size_t length = inName.size();
char const* name = inName.c_str();
+ if (length == 0) {
+ return name;
+ }
+
size_t last = length - 1;
if (last > 0 && (name[last] == '/' || name[last] == '\\') &&
- strcmp(name, "/") != 0 && name[last - 1] != ':') {
+ name[last - 1] != ':') {
if (last < sizeof(local_buffer)) {
memcpy(local_buffer, name, last);
local_buffer[last] = '\0';
@@ -3076,6 +3080,10 @@
bool SystemTools::FileIsExecutable(std::string const& inName)
{
+ if (inName.empty()) {
+ return false;
+ }
+
#ifdef _WIN32
char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
std::string string_buffer;
@@ -3970,7 +3978,7 @@
std::string temp = dir;
if (need_slash) {
- temp += "/";
+ temp += '/';
}
temp += filename_base;
@@ -4000,11 +4008,11 @@
break;
}
- filename_dir_bases = filename_dir_base + "/" + filename_dir_bases;
+ filename_dir_bases = filename_dir_base + '/' + filename_dir_bases;
temp = dir;
if (need_slash) {
- temp += "/";
+ temp += '/';
}
temp += filename_dir_bases;
@@ -4128,7 +4136,7 @@
{
std::string str(s);
if (str.find_first_of("0123456789") == 0) {
- str = "_" + str;
+ str = '_' + str;
}
std::string permited_chars("_"
@@ -4523,10 +4531,10 @@
res += " Advanced Server";
}
- res += " ";
+ res += ' ';
snprintf(buffer, sizeof(buffer), "%ld", osvi.dwMajorVersion);
res += buffer;
- res += ".";
+ res += '.';
snprintf(buffer, sizeof(buffer), "%ld", osvi.dwMinorVersion);
res += buffer;
}
@@ -4549,26 +4557,26 @@
res += " Service Pack 6a (Build ";
snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
- res += ")";
+ res += ')';
} else // Windows NT 4.0 prior to SP6a
{
- res += " ";
+ res += ' ';
res += osvi.szCSDVersion;
res += " (Build ";
snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
- res += ")";
+ res += ')';
}
RegCloseKey(hKey);
} else // Windows NT 3.51 and earlier or Windows 2000 and later
{
- res += " ";
+ res += ' ';
res += osvi.szCSDVersion;
res += " (Build ";
snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
- res += ")";
+ res += ')';
}
break;
diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in
index e7693e2..70ec551 100644
--- a/Templates/TestDriver.cxx.in
+++ b/Templates/TestDriver.cxx.in
@@ -88,6 +88,7 @@
{
int i;
int testNum = 0;
+ int show_only;
int partial_match;
int run_all;
char *arg;
@@ -117,14 +118,22 @@
ac--;
av++;
}
+ show_only = 0;
partial_match = 0;
run_all = 0;
arg = CM_NULL; /* NOLINT */
/* If partial match or running all tests are requested. */
if (testToRun == -1 && ac > 1) {
+ show_only = (strcmp(av[1], "-N") == 0) ? 1 : 0;
partial_match = (strcmp(av[1], "-R") == 0) ? 1 : 0;
run_all = (strcmp(av[1], "-A") == 0) ? 1 : 0;
}
+ if (show_only == 1) {
+ for (i = 0; i < NumTests; ++i) {
+ printf("%s\n", cmakeGeneratedFunctionMapEntries[i].name);
+ }
+ return 0;
+ }
if (partial_match != 0 && ac < 3) {
printf("-R needs an additional parameter.\n");
return -1;
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index cbb7fdf..599dde1 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -18,6 +18,7 @@
testRange.cxx
testOptional.cxx
testPathResolver.cxx
+ testScriptGenerator.cxx
testSpdxSerializer.cxx
testStdIo.cxx
testString.cxx
diff --git a/Tests/CMakeLib/testCMExtAlgorithm.cxx b/Tests/CMakeLib/testCMExtAlgorithm.cxx
index 53b0302..0f00bd3 100644
--- a/Tests/CMakeLib/testCMExtAlgorithm.cxx
+++ b/Tests/CMakeLib/testCMExtAlgorithm.cxx
@@ -1,5 +1,8 @@
#include <iostream>
+#include <map>
#include <memory>
+#include <string>
+#include <tuple>
#include <utility>
#include <vector>
@@ -107,11 +110,79 @@
}
}
}
+
+void testKeys()
+{
+ {
+ std::map<std::string, int> m{ { "one", 1 }, { "two", 2 } };
+ std::vector<std::string> ref{ "one", "two" };
+
+ auto res = cm::keys(m);
+ if (res != ref) {
+ ++failed;
+ }
+ }
+ {
+ std::map<int, int> m{ { 1, 1 }, { 2, 2 } };
+ std::vector<int> ref{ 1, 2 };
+
+ auto res = cm::keys(m);
+ if (res != ref) {
+ ++failed;
+ }
+ }
+ {
+ std::vector<std::tuple<std::string, int, int>> m;
+ m.emplace_back("one", 1, 10);
+ m.emplace_back("two", 2, 20);
+ std::vector<std::string> ref{ "one", "two" };
+
+ auto res = cm::keys(m);
+ if (res != ref) {
+ ++failed;
+ }
+ }
+}
+
+void testValues()
+{
+ {
+ std::map<std::string, int> m{ { "one", 1 }, { "two", 2 } };
+ std::vector<int> ref{ 1, 2 };
+
+ auto res = cm::values(m);
+ if (res != ref) {
+ ++failed;
+ }
+ }
+ {
+ std::map<int, std::string> m{ { 1, "one" }, { 2, "two" } };
+ std::vector<std::string> ref{ "one", "two" };
+
+ auto res = cm::values(m);
+ if (res != ref) {
+ ++failed;
+ }
+ }
+ {
+ std::vector<std::tuple<std::string, int, int>> m;
+ m.emplace_back("one", 1, 10);
+ m.emplace_back("two", 2, 20);
+ std::vector<int> ref{ 1, 2 };
+
+ auto res = cm::values(m);
+ if (res != ref) {
+ ++failed;
+ }
+ }
+}
}
int testCMExtAlgorithm(int /*unused*/, char* /*unused*/[])
{
testAppend();
+ testKeys();
+ testValues();
return failed;
}
diff --git a/Tests/CMakeLib/testDebugger.h b/Tests/CMakeLib/testDebugger.h
index c27086d..7b43b19 100644
--- a/Tests/CMakeLib/testDebugger.h
+++ b/Tests/CMakeLib/testDebugger.h
@@ -8,7 +8,6 @@
#include "cmDebuggerAdapter.h"
#include "cmDebuggerProtocol.h"
#include "cmListFileCache.h"
-#include "cmMessenger.h"
#include <cmcppdap/include/dap/io.h>
#include <cmcppdap/include/dap/session.h>
#include <cmcppdap/include/dap/types.h>
@@ -72,13 +71,12 @@
Client->bind(server2client, client2server);
Debugger->bind(client2server, server2client);
}
- std::vector<cmListFileFunction> CreateListFileFunctions(char const* str,
- char const* filename)
+ std::vector<cmListFileFunction> CreateListFileFunctions(
+ char const* str, std::string const& filename)
{
- cmMessenger messenger;
cmListFileBacktrace backtrace;
cmListFile listfile;
- listfile.ParseString(str, filename, &messenger, backtrace);
+ listfile.ParseString(str, filename, nullptr, backtrace);
return listfile.Functions;
}
};
diff --git a/Tests/CMakeLib/testDebuggerAdapterPipe.cxx b/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
index d7c4134..a7af6e8 100644
--- a/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
+++ b/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
@@ -7,6 +7,7 @@
#include <memory>
#include <stdexcept>
#include <string>
+#include <thread>
#include <cm3p/cppdap/future.h>
#include <cm3p/cppdap/io.h>
@@ -173,7 +174,157 @@
return true;
}
+bool testProtocolWithPipesAbruptDisconnect()
+{
+ std::promise<void> debuggerConnectionCreatedPromise;
+ std::future<void> debuggerConnectionCreatedFuture =
+ debuggerConnectionCreatedPromise.get_future();
+
+ std::future<void> startedListeningFuture;
+
+ std::promise<void> adapterFinishedPromise;
+ std::future<void> adapterFinishedFuture =
+ adapterFinishedPromise.get_future();
+
+ std::promise<bool> initializedEventReceivedPromise;
+ std::future<bool> initializedEventReceivedFuture =
+ initializedEventReceivedPromise.get_future();
+
+ std::promise<bool> exitedEventReceivedPromise;
+ std::future<bool> exitedEventReceivedFuture =
+ exitedEventReceivedPromise.get_future();
+
+ std::promise<bool> terminatedEventReceivedPromise;
+ std::future<bool> terminatedEventReceivedFuture =
+ terminatedEventReceivedPromise.get_future();
+
+ std::promise<bool> threadStartedPromise;
+ std::future<bool> threadStartedFuture = threadStartedPromise.get_future();
+
+ std::promise<bool> threadExitedPromise;
+ std::future<bool> threadExitedFuture = threadExitedPromise.get_future();
+
+ auto futureTimeout = std::chrono::seconds(60);
+ auto disconnectTimeout = std::chrono::seconds(10);
+
+#ifdef _WIN32
+ std::string namedPipe = R"(\\.\pipe\LOCAL\CMakeDebuggerPipe3_)" +
+ cmCryptoHash(cmCryptoHash::AlgoSHA256)
+ .HashString(cmsys::SystemTools::GetCurrentWorkingDirectory());
+#else
+ std::string namedPipe = "CMakeDebuggerPipe3";
+#endif
+
+ std::unique_ptr<dap::Session> client = dap::Session::create();
+ client->registerHandler([&](dap::InitializedEvent /*unused*/) {
+ initializedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](dap::ExitedEvent /*unused*/) {
+ exitedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](dap::TerminatedEvent const& /*unused*/) {
+ terminatedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](dap::ThreadEvent const& e) {
+ if (e.reason == "started") {
+ threadStartedPromise.set_value(true);
+ } else if (e.reason == "exited") {
+ threadExitedPromise.set_value(true);
+ }
+ });
+
+ // Raw thread (not ScopedThread): we need to be able to detach on
+ // failure so the test process can exit even if the regression
+ // returns. With the fix in place, ReportExitCode()'s wait on
+ // DisconnectEvent unblocks when the SessionThread detects EOF on the
+ // pipe; without the fix, it blocks forever and the adapter
+ // destructor hangs in SessionThread.join().
+ std::thread debuggerThread([&]() {
+ try {
+ auto connection =
+ std::make_shared<cmDebugger::cmDebuggerPipeConnection>(namedPipe);
+ startedListeningFuture = connection->StartedListening.get_future();
+ debuggerConnectionCreatedPromise.set_value();
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> debuggerAdapter =
+ std::make_shared<cmDebugger::cmDebuggerAdapter>(
+ connection, dap::file(stdout, false));
+ // Sends thread-exited / exited / terminated events and then
+ // blocks on DisconnectEvent. The test closes the client side of
+ // the pipe instead of sending a DisconnectRequest, so the only
+ // thing that will unblock this wait is the SessionThread's EOF
+ // handling in cmDebuggerAdapter.
+ debuggerAdapter->ReportExitCode(0);
+ // Adapter destructed here; joins SessionThread.
+ } catch (std::runtime_error const&) {
+ // Swallowed: connection failures shouldn't hang the test.
+ }
+ adapterFinishedPromise.set_value();
+ });
+
+ ASSERT_TRUE(debuggerConnectionCreatedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(startedListeningFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+
+ auto client2Debugger =
+ std::make_shared<cmDebugger::cmDebuggerPipeClient>(namedPipe);
+ client2Debugger->WaitForConnection();
+ client->bind(client2Debugger, client2Debugger);
+
+ // Drive the full handshake so that the debugger SessionThread is up
+ // and ReportExitCode is blocked on DisconnectEvent.
+ dap::CMakeInitializeRequest initializeRequest;
+ auto initializeResponse = client->send(initializeRequest).get();
+ ASSERT_TRUE(!initializeResponse.error);
+
+ dap::LaunchRequest launchRequest;
+ auto launchResponse = client->send(launchRequest).get();
+ ASSERT_TRUE(!launchResponse.error);
+
+ dap::ConfigurationDoneRequest configurationDoneRequest;
+ auto configurationDoneResponse =
+ client->send(configurationDoneRequest).get();
+ ASSERT_TRUE(!configurationDoneResponse.error);
+
+ ASSERT_TRUE(initializedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(terminatedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(threadStartedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(threadExitedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(exitedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+
+ // Abruptly close the client side without sending DisconnectRequest.
+ // Regression check for the busy-loop bug: the debugger adapter must
+ // detect EOF on the pipe and shut down on its own.
+ //
+ // Use ShutdownForTesting() rather than close(). The client dap::Session
+ // has its own recvThread still blocked in read() on this same socket;
+ // on Linux, ::close() on an fd does not wake a sibling thread's
+ // in-flight ::read(), which would deadlock the test. ShutdownForTesting
+ // calls shutdown(SHUT_RDWR) to signal EOF on the socket endpoint
+ // without freeing the fd, so both reads wake up naturally.
+ client2Debugger->ShutdownForTesting();
+
+ bool finishedInTime = adapterFinishedFuture.wait_for(disconnectTimeout) ==
+ std::future_status::ready;
+ if (!finishedInTime) {
+ // Bug reproduced: the SessionThread is spinning on EOF and
+ // ReportExitCode is blocked on DisconnectEvent. Detach so the test
+ // process can exit instead of hanging in std::thread's destructor.
+ debuggerThread.detach();
+ ASSERT_TRUE(finishedInTime);
+ }
+ debuggerThread.join();
+
+ return true;
+}
+
int testDebuggerAdapterPipe(int, char*[])
{
- return runTests({ testProtocolWithPipes });
+ return runTests(
+ { testProtocolWithPipes, testProtocolWithPipesAbruptDisconnect });
}
diff --git a/Tests/CMakeLib/testDebuggerBreakpointManager.cxx b/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
index 3fff39e..527053d 100644
--- a/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
+++ b/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
@@ -75,8 +75,7 @@
helper.bind();
std::string sourcePath = "C:/CMakeLists.txt";
std::vector<cmListFileFunction> functions = helper.CreateListFileFunctions(
- "# Comment1\nset(var1 foo)\n# Comment2\nset(var2\nbar)\n",
- sourcePath.c_str());
+ "# Comment1\nset(var1 foo)\n# Comment2\nset(var2\nbar)\n", sourcePath);
breakpointManager.SourceFileLoaded(sourcePath, functions);
dap::SetBreakpointsRequest setBreakpointRequest;
@@ -149,8 +148,7 @@
sourceBreakpoints[4].line = 5;
setBreakpointRequest.breakpoints = sourceBreakpoints;
std::vector<cmListFileFunction> functions = helper.CreateListFileFunctions(
- "# Comment1\nset(var1 foo)\n# Comment2\nset(var2\nbar)\n",
- sourcePath.c_str());
+ "# Comment1\nset(var1 foo)\n# Comment2\nset(var2\nbar)\n", sourcePath);
auto got = helper.Client->send(setBreakpointRequest).get();
// Act
diff --git a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
index aa21c58..e408d4c 100644
--- a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
+++ b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
@@ -18,6 +18,7 @@
#include "cmDebuggerVariablesHelper.h"
#include "cmDebuggerVariablesManager.h"
#include "cmFileSet.h"
+#include "cmFileSetMetadata.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
@@ -501,8 +502,9 @@
std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
auto dummies = CreateDummies("Foo");
- cmFileSet fileSet(dummies.Makefile.get(), "Foo", "HEADERS",
- cmFileSetVisibility::Public);
+ cmFileSet fileSet(dummies.Makefile.get(),
+ dummies.Makefile->GetOrderedTargets()[0], "Foo", "HEADERS",
+ cm::FileSetMetadata::Visibility::Public);
BT<std::string> directory;
directory.Value = "c:/";
fileSet.AddDirectoryEntry(directory);
@@ -546,8 +548,9 @@
std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
auto dummies = CreateDummies("Foo");
- cmFileSet fileSet(dummies.Makefile.get(), "Foo", "HEADERS",
- cmFileSetVisibility::Public);
+ cmFileSet fileSet(dummies.Makefile.get(),
+ dummies.Makefile->GetOrderedTargets()[0], "Foo", "HEADERS",
+ cm::FileSetMetadata::Visibility::Public);
BT<std::string> directory;
directory.Value = "c:/";
fileSet.AddDirectoryEntry(directory);
diff --git a/Tests/CMakeLib/testScriptGenerator.cxx b/Tests/CMakeLib/testScriptGenerator.cxx
new file mode 100644
index 0000000..defa5f8
--- /dev/null
+++ b/Tests/CMakeLib/testScriptGenerator.cxx
@@ -0,0 +1,35 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+
+#include <string>
+
+#include "cmScriptGenerator.h"
+
+#include "testCommon.h"
+
+#define TEST_QUOTE(input, expected_output) \
+ ASSERT_EQUAL(cmScriptGenerator::Quote(input).str(), (expected_output))
+
+namespace {
+
+bool quote()
+{
+ TEST_QUOTE("", "\"\"");
+ TEST_QUOTE("\"", "[[\"]]");
+ TEST_QUOTE("\\", "[[\\]]");
+ TEST_QUOTE("$", "[[$]]");
+ TEST_QUOTE("$]", "[=[$]]=]");
+ TEST_QUOTE("$]=", "[[$]=]]");
+ TEST_QUOTE("$]=]", "[==[$]=]]==]");
+ TEST_QUOTE("$]==]", "[=[$]==]]=]");
+ return true;
+}
+
+} // namespace
+
+int testScriptGenerator(int /*unused*/, char* /*unused*/[])
+{
+ return runTests({
+ quote,
+ });
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 5c2a6e6..57d40ce 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -131,7 +131,9 @@
set(CMake_TEST_RESOURCES TRUE)
endif()
# For some Windows toolchains there is no resource support.
- if(WATCOM OR BORLAND OR CMAKE_C_COMPILER_ID STREQUAL "OrangeC")
+ if(WATCOM OR BORLAND
+ OR (CMAKE_C_COMPILER_ID STREQUAL "OrangeC" AND
+ CMAKE_C_COMPILER_VERSION VERSION_LESS "7.0"))
set(CMake_TEST_RESOURCES FALSE)
endif()
@@ -262,6 +264,10 @@
unset(_sysctl_stdout)
endif()
+ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA MATCHES "^(NVIDIA|Clang)$")
+ message(FATAL_ERROR "CMake_TEST_CUDA should be \"NVIDIA\" or \"Clang\", got \"${CMake_TEST_CUDA}\"")
+ endif()
+
#---------------------------------------------------------------------------
# Add tests below here.
@@ -464,6 +470,7 @@
if(CMake_TEST_Rust)
ADD_TEST_MACRO(RustOnly RustOnly)
ADD_TEST_MACRO(RustMix RustMix)
+ ADD_TEST_MACRO(RustPie RustPie)
endif()
if(CMAKE_Fortran_COMPILER)
ADD_TEST_MACRO(FortranOnly FortranOnly)
@@ -523,6 +530,7 @@
endif()
ADD_TEST_MACRO(COnly COnly)
+ set_property(TEST COnly APPEND PROPERTY LABELS "PellesC")
ADD_TEST_MACRO(CxxOnly CxxOnly)
ADD_TEST_MACRO(CxxSubdirC CxxSubdirC)
ADD_TEST_MACRO(OutDir runtime/OutDir)
@@ -3014,7 +3022,7 @@
)
#make sure all 3 subdirs were added
set_tests_properties(CTestTestSubdir PROPERTIES
- PASS_REGULAR_EXPRESSION "0 tests failed out of 3")
+ PASS_REGULAR_EXPRESSION "100% tests passed out of 3")
configure_file(
"${CMake_SOURCE_DIR}/Tests/CTestTestDepends/test.cmake.in"
diff --git a/Tests/COnly/libc2.c b/Tests/COnly/libc2.c
index 28d46f3..c36bc6d 100644
--- a/Tests/COnly/libc2.c
+++ b/Tests/COnly/libc2.c
@@ -1,5 +1,8 @@
#include "libc2.h"
+#ifdef __POCC__
+CM_TEST_LIB_EXPORT
+#endif
float LibC2Func(void)
{
return 1.0;
diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
index 07281ed..e2664b6 100644
--- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
@@ -390,26 +390,23 @@
file(GLOB_RECURSE symlink_files RELATIVE "${CPackComponentsForAll_BINARY_DIR}" "${CPackComponentsForAll_BINARY_DIR}/*/symlink_*")
foreach(check_symlink IN LISTS symlink_files)
- get_filename_component(symlink_name "${check_symlink}" NAME)
- execute_process(COMMAND ls -la "${check_symlink}"
- WORKING_DIRECTORY "${CPackComponentsForAll_BINARY_DIR}"
- OUTPUT_VARIABLE SYMLINK_POINT_
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ cmake_path(GET check_symlink FILENAME symlink_name)
+ file(READ_SYMLINK "${check_symlink}" symlink_dst)
if("${symlink_name}" STREQUAL "symlink_samedir_path"
OR "${symlink_name}" STREQUAL "symlink_samedir_path_current_dir"
OR "${symlink_name}" STREQUAL "symlink_samedir_path_longer")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}depth_three$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^depth_three$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_subdir_path")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}depth_two/depth_three$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^depth_two/depth_three$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_parentdir_path")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}../$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^\.\.$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_to_non_relocatable_path")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/non_relocatable/depth_two$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^${CPACK_PACKAGING_INSTALL_PREFIX}/non_relocatable/depth_two$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_outside_package")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}outside_package$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^outside_package$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_outside_wdr")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}/outside_package_wdr$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^/outside_package_wdr$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_other_relocatable_path"
OR "${symlink_name}" STREQUAL "symlink_from_non_relocatable_path"
OR "${symlink_name}" STREQUAL "symlink_relocatable_subpath")
@@ -419,7 +416,7 @@
endif()
if(NOT check_symlink)
- message(FATAL_ERROR "symlink points to unexpected location '${SYMLINK_POINT_}'")
+ message(FATAL_ERROR "symlink points to unexpected location '${symlink_dst}'")
endif()
endforeach()
diff --git a/Tests/CPackNSISGenerator/CMakeLists.txt b/Tests/CPackNSISGenerator/CMakeLists.txt
index 569a478..ed4a264 100644
--- a/Tests/CPackNSISGenerator/CMakeLists.txt
+++ b/Tests/CPackNSISGenerator/CMakeLists.txt
@@ -40,6 +40,7 @@
set(CPACK_NSIS_BRANDING_TEXT "CMake branding text")
set(CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION "RIGHT")
set(CPACK_NSIS_IGNORE_LICENSE_PAGE ON)
+set(CPACK_NSIS_IGNORE_COMPONENTS_PAGE ON)
set(CPACK_NSIS_CRC_CHECK "off")
include(CPack)
diff --git a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
index e811deb..66a1124 100644
--- a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
+++ b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
@@ -70,6 +70,15 @@
message(FATAL_ERROR "License found in the project")
endif()
+# components page should not be present
+file(STRINGS "${project_file}" line REGEX "!insertmacro MUI_PAGE_COMPONENTS")
+string(FIND "${line}" "MUI_PAGE_COMPONENTS" output_index)
+if("${output_index}" EQUAL "-1")
+ message(STATUS "Components page not found in the project")
+else()
+ message(FATAL_ERROR "Components page found in the project")
+endif()
+
file(STRINGS "${project_file}" line REGEX [[\\_CON\\]])
string(FIND "${line}" [[\_CON\]] output_index)
message(STATUS "Found CON component reserved directory name as _CON")
diff --git a/Tests/CompileFeatures/cxx_std.h b/Tests/CompileFeatures/cxx_std.h
index f17b683..c9d9ecf 100644
--- a/Tests/CompileFeatures/cxx_std.h
+++ b/Tests/CompileFeatures/cxx_std.h
@@ -28,7 +28,9 @@
# define CXX_STD __cplusplus
# endif
#elif defined(__NVCOMPILER)
-# if __cplusplus == CXX_STD_17 && defined(__cpp_aggregate_paren_init)
+# if __cplusplus > CXX_STD_20 && defined(__cpp_pp_embed)
+# define CXX_STD /*CXX_STD_26*/ (CXX_STD_23 + 1)
+# elif __cplusplus == CXX_STD_17 && defined(__cpp_aggregate_paren_init)
# define CXX_STD CXX_STD_20
# else
# define CXX_STD __cplusplus
diff --git a/Tests/ExportImport/InitialCache.cmake.in b/Tests/ExportImport/InitialCache.cmake.in
index 55aef86..0494d40 100644
--- a/Tests/ExportImport/InitialCache.cmake.in
+++ b/Tests/ExportImport/InitialCache.cmake.in
@@ -14,5 +14,5 @@
set(CMAKE_INSTALL_PREFIX "@ExportImport_BINARY_DIR@/Root" CACHE STRING "Installation Prefix")
set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH")
set(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS")
-set(CMake_TEST_CUDA "@CMake_TEST_CUDA@" CACHE BOOL "CMake_TEST_CUDA")
+set(CMake_TEST_CUDA "@CMake_TEST_CUDA@" CACHE STRING "CMake_TEST_CUDA")
set(Foo_DIR "@CMAKE_CURRENT_SOURCE_DIR@/External" CACHE PATH "Foo cmake package directory")
diff --git a/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx b/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx
index cebd50f..adc02e5 100644
--- a/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx
+++ b/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx
@@ -22,11 +22,12 @@
fprintf(fout, "double sqrtTable[] = {\n");
for (i = 0; i < 10; ++i) {
result = sqrt(static_cast<double>(i));
- fprintf(fout, "%g,\n", result);
+ // FIXME(OrangeC#1138): OrangeC 7 no longer accepts plain '0' as a double
+ fprintf(fout, "%.5f,\n", result);
}
// close the table with a zero
- fprintf(fout, "0};\n");
+ fprintf(fout, "0.0};\n");
fclose(fout);
return 0;
}
diff --git a/Tests/Fuzzing/cmArchiveExtractFuzzer.cxx b/Tests/Fuzzing/cmArchiveExtractFuzzer.cxx
index a4f66b6..4fb2b73 100644
--- a/Tests/Fuzzing/cmArchiveExtractFuzzer.cxx
+++ b/Tests/Fuzzing/cmArchiveExtractFuzzer.cxx
@@ -87,7 +87,8 @@
// Extract without verbose, with timestamps
bool result1 = cmSystemTools::ExtractTar(
- archiveFile, files, cmSystemTools::cmTarExtractTimestamps::Yes, false);
+ archiveFile, files, cmSystemTools::cmTarExtractTimestamps::Yes, "UTF-8",
+ false);
(void)result1;
// Restore directory BEFORE removing (can't remove cwd)
@@ -102,7 +103,8 @@
// Extract with verbose, without timestamps
files.clear();
bool result2 = cmSystemTools::ExtractTar(
- archiveFile, files, cmSystemTools::cmTarExtractTimestamps::No, true);
+ archiveFile, files, cmSystemTools::cmTarExtractTimestamps::No, "UTF-8",
+ true);
(void)result2;
// Restore directory
diff --git a/Tests/Fuzzing/cmListFileParserFuzzer.cxx b/Tests/Fuzzing/cmListFileParserFuzzer.cxx
index 4908713..6632d25 100644
--- a/Tests/Fuzzing/cmListFileParserFuzzer.cxx
+++ b/Tests/Fuzzing/cmListFileParserFuzzer.cxx
@@ -20,7 +20,6 @@
#include <unistd.h>
#include "cmListFileCache.h"
-#include "cmMessenger.h"
#include "cmSystemTools.h"
static constexpr size_t kMaxInputSize = 256 * 1024;
@@ -59,13 +58,10 @@
fclose(fp);
}
- // Create a messenger for error handling
- cmMessenger messenger;
-
// Parse the file
cmListFile listFile;
cmListFileBacktrace backtrace;
- if (listFile.ParseFile(testFile.c_str(), &messenger, backtrace)) {
+ if (listFile.ParseFile(testFile.c_str(), nullptr, backtrace)) {
// Successfully parsed - examine results
for (auto const& func : listFile.Functions) {
(void)func.LowerCaseName();
diff --git a/Tests/GoogleTest/Test/CMakeLists.txt b/Tests/GoogleTest/Test/CMakeLists.txt
index 0735496..43848c0 100644
--- a/Tests/GoogleTest/Test/CMakeLists.txt
+++ b/Tests/GoogleTest/Test/CMakeLists.txt
@@ -114,3 +114,15 @@
if(NOT TEST GoogleTest.NoKeywords)
message(FATAL_ERROR "Test case GoogleTest.NoKeywords not defined")
endif()
+
+# Check if LIST_SEPARATOR allows passing both ENVIRONMENT values to test
+add_executable(test_gtest5 main5.cxx)
+target_link_libraries(test_gtest5 GTest::Main)
+set(environment VALX=1 VALY=2)
+set(list_separator ",")
+list(JOIN environment ${list_separator} environment)
+gtest_discover_tests(test_gtest5
+ LIST_SEPARATOR ${list_separator}
+ PROPERTIES
+ ENVIRONMENT "${environment}"
+)
diff --git a/Tests/GoogleTest/Test/main1.cxx b/Tests/GoogleTest/Test/main1.cxx
index c353d91..3e50398 100644
--- a/Tests/GoogleTest/Test/main1.cxx
+++ b/Tests/GoogleTest/Test/main1.cxx
@@ -20,11 +20,10 @@
{
::testing::InitGoogleTest(&argc, argv);
- if (argc > 1) {
- if (argv[1] != std::string("--forceFail")) {
- throw "Unexpected argument";
+ for (int i = 0; i < argc; ++i) {
+ if (argv[i] == std::string("--forceFail")) {
+ shouldFail = true;
}
- shouldFail = true;
}
return RUN_ALL_TESTS();
}
diff --git a/Tests/GoogleTest/Test/main5.cxx b/Tests/GoogleTest/Test/main5.cxx
new file mode 100644
index 0000000..28fa374
--- /dev/null
+++ b/Tests/GoogleTest/Test/main5.cxx
@@ -0,0 +1,9 @@
+#include <cstdlib>
+
+#include <gtest/gtest.h>
+
+TEST(GoogleTest, Add)
+{
+ EXPECT_STREQ(std::getenv("VALX"), "1");
+ EXPECT_STREQ(std::getenv("VALY"), "2");
+}
diff --git a/Tests/Module/ExternalData/CMakeLists.txt b/Tests/Module/ExternalData/CMakeLists.txt
index c09c693..bda1149 100644
--- a/Tests/Module/ExternalData/CMakeLists.txt
+++ b/Tests/Module/ExternalData/CMakeLists.txt
@@ -57,3 +57,4 @@
add_subdirectory(Data4)
add_subdirectory(Data5)
add_subdirectory(DataNoSymlinks)
+add_subdirectory(DataStateRoot)
diff --git a/Tests/Module/ExternalData/DataStateRoot/CMakeLists.txt b/Tests/Module/ExternalData/DataStateRoot/CMakeLists.txt
new file mode 100644
index 0000000..eb8595f
--- /dev/null
+++ b/Tests/Module/ExternalData/DataStateRoot/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(ExternalData_STATE_ROOT "${CMAKE_CURRENT_BINARY_DIR}/State")
+ExternalData_Add_Test(DataStateRoot
+ NAME DataStateRootCheck
+ COMMAND ${CMAKE_COMMAND}
+ -D Data=DATA{Data.dat}
+ -D AdjacentHash=${ExternalData_BINARY_ROOT}/DataStateRoot/Data.dat-hash-stamp
+ -D StateHash=${ExternalData_STATE_ROOT}/DataStateRoot/Data.dat-hash-stamp
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/DataStateRootCheck.cmake
+ )
+ExternalData_Add_Target(DataStateRoot)
diff --git a/Tests/Module/ExternalData/DataStateRoot/Data.dat.md5 b/Tests/Module/ExternalData/DataStateRoot/Data.dat.md5
new file mode 100644
index 0000000..70e39bd
--- /dev/null
+++ b/Tests/Module/ExternalData/DataStateRoot/Data.dat.md5
@@ -0,0 +1 @@
+8c018830e3efa5caf3c7415028335a57
diff --git a/Tests/Module/ExternalData/DataStateRoot/DataStateRootCheck.cmake b/Tests/Module/ExternalData/DataStateRoot/DataStateRootCheck.cmake
new file mode 100644
index 0000000..869c877
--- /dev/null
+++ b/Tests/Module/ExternalData/DataStateRoot/DataStateRootCheck.cmake
@@ -0,0 +1,9 @@
+if(NOT EXISTS "${Data}")
+ message(SEND_ERROR "Input file:\n ${Data}\n" "does not exist!")
+endif()
+if(EXISTS "${AdjacentHash}")
+ message(SEND_ERROR "Adjacent hash record exists but should not:\n ${AdjacentHash}")
+endif()
+if(NOT EXISTS "${StateHash}")
+ message(SEND_ERROR "State-root hash record is missing:\n ${StateHash}")
+endif()
diff --git a/Tests/RunCMake/CMP0119/RunCMakeTest.cmake b/Tests/RunCMake/CMP0119/RunCMakeTest.cmake
index 2576a28..da93a9c 100644
--- a/Tests/RunCMake/CMP0119/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMP0119/RunCMakeTest.cmake
@@ -12,6 +12,8 @@
run_CMP0119(WARN)
run_CMP0119(OLD)
endif()
-if((CMAKE_C_COMPILER_ID MATCHES "(GNU|LCC|Clang|MSVC|Borland|Embarcadero|Intel|TI|OrangeC)"))
+if((CMAKE_C_COMPILER_ID MATCHES "(GNU|LCC|Clang|MSVC|Borland|Embarcadero|Intel|TI)")
+ # FIXME(OrangeC#1137): OrangeC 7 no longer accepts custom file extensions with -x
+ OR (CMAKE_C_COMPILER_ID STREQUAL "OrangeC" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 7))
run_CMP0119(NEW)
endif()
diff --git a/Tests/RunCMake/CMP0152/CMP0152-OLD-stderr.txt b/Tests/RunCMake/CMP0152/CMP0152-OLD-stderr.txt
index e69de29..c4ff034 100644
--- a/Tests/RunCMake/CMP0152/CMP0152-OLD-stderr.txt
+++ b/Tests/RunCMake/CMP0152/CMP0152-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0152-OLD\.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0152 will be removed from a future version
+ of CMake\.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances\. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMP0153/CMP0153-OLD-stderr.txt b/Tests/RunCMake/CMP0153/CMP0153-OLD-stderr.txt
new file mode 100644
index 0000000..5ac6da4
--- /dev/null
+++ b/Tests/RunCMake/CMP0153/CMP0153-OLD-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Deprecation Warning at [^
+]*/Tests/RunCMake/CMP0153/CMP0153-OLD\.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0153 will be removed from a future version
+ of CMake\.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances\. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD\.$
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-none-Debug-build-result.txt b/Tests/RunCMake/CMP0212/CMP0212-NEW-build-result.txt
similarity index 100%
rename from Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-none-Debug-build-result.txt
rename to Tests/RunCMake/CMP0212/CMP0212-NEW-build-result.txt
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-none-Debug-build-stderr.txt b/Tests/RunCMake/CMP0212/CMP0212-NEW-build-stdout.txt
similarity index 100%
rename from Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-none-Debug-build-stderr.txt
rename to Tests/RunCMake/CMP0212/CMP0212-NEW-build-stdout.txt
diff --git a/Tests/RunCMake/CMP0212/CMP0212-common-exe.cmake b/Tests/RunCMake/CMP0212/CMP0212-common-exe.cmake
new file mode 100644
index 0000000..05eda9f
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/CMP0212-common-exe.cmake
@@ -0,0 +1,2 @@
+add_executable(foo main.c)
+set_target_properties(foo PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin)
diff --git a/Tests/RunCMake/CMP0212/CMakeLists.txt b/Tests/RunCMake/CMP0212/CMakeLists.txt
new file mode 100644
index 0000000..b18faf4
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 4.3)
+project(${RunCMake_TEST} C)
+include(CMP0212-common-exe.cmake)
+add_subdirectory(subdir)
diff --git a/Tests/RunCMake/CMP0212/RunCMakeTest.cmake b/Tests/RunCMake/CMP0212/RunCMakeTest.cmake
new file mode 100644
index 0000000..d4a0747
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/RunCMakeTest.cmake
@@ -0,0 +1,12 @@
+include(RunCMake)
+
+function(run_cmake_case_cmp0212 case)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
+ run_cmake(${case})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --target ${ARGN})
+endfunction()
+
+run_cmake_case_cmp0212(CMP0212-OLD tgt1)
+run_cmake_case_cmp0212(CMP0212-NEW tgt1 bar)
diff --git a/Tests/RunCMake/CMP0212/main.c b/Tests/RunCMake/CMP0212/main.c
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/main.c
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CMP0212/subdir/CMP0212-NEW.cmake b/Tests/RunCMake/CMP0212/subdir/CMP0212-NEW.cmake
new file mode 100644
index 0000000..9568a4a
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/subdir/CMP0212-NEW.cmake
@@ -0,0 +1,11 @@
+cmake_policy(SET CMP0212 NEW)
+include(CMP0212-common-custom.cmake)
+
+# Define an executable with a different target name so that the above custom
+# command finds the file-level dependency instead of the target-level
+# dependency, and thus fails the build by compiling a bad C file.
+add_executable(bar bad.c)
+set_target_properties(bar PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "$<1:${CMAKE_CURRENT_BINARY_DIR}>"
+ RUNTIME_OUTPUT_NAME foo
+)
diff --git a/Tests/RunCMake/CMP0212/subdir/CMP0212-OLD.cmake b/Tests/RunCMake/CMP0212/subdir/CMP0212-OLD.cmake
new file mode 100644
index 0000000..05b4849
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/subdir/CMP0212-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0212 OLD)
+include(CMP0212-common-custom.cmake)
diff --git a/Tests/RunCMake/CMP0212/subdir/CMP0212-common-custom.cmake b/Tests/RunCMake/CMP0212/subdir/CMP0212-common-custom.cmake
new file mode 100644
index 0000000..d5f2c9e
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/subdir/CMP0212-common-custom.cmake
@@ -0,0 +1,6 @@
+add_custom_command(
+ OUTPUT cmd1
+ COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/cmd1"
+ DEPENDS foo.exe
+)
+add_custom_target(tgt1 DEPENDS cmd1)
diff --git a/Tests/RunCMake/CMP0212/subdir/CMakeLists.txt b/Tests/RunCMake/CMP0212/subdir/CMakeLists.txt
new file mode 100644
index 0000000..a7cff2b
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/subdir/CMakeLists.txt
@@ -0,0 +1 @@
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0212/subdir/bad.c b/Tests/RunCMake/CMP0212/subdir/bad.c
new file mode 100644
index 0000000..a364cfd
--- /dev/null
+++ b/Tests/RunCMake/CMP0212/subdir/bad.c
@@ -0,0 +1 @@
+#error "This is an invalid C file."
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 6d23fc8..b763eb7 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -139,7 +139,8 @@
add_RunCMake_test(CMP0116)
endif()
add_RunCMake_test(CMP0118)
-add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
+add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
+ -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION})
add_RunCMake_test(CMP0121)
if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)")
add_RunCMake_test(CMP0125 -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
@@ -180,6 +181,9 @@
add_RunCMake_test(CMP0171)
add_RunCMake_test(CMP0173)
add_RunCMake_test(CMP0187)
+if(WIN32)
+ add_RunCMake_test(CMP0212)
+endif()
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
add_RunCMake_test(CMP0194 -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION})
@@ -408,7 +412,9 @@
add_RunCMake_test(CpsExportImportBuild)
add_RunCMake_test(CpsExportImportInstall)
add_RunCMake_test(CpsMapConfig)
+add_RunCMake_test(create_test_sourcelist)
add_RunCMake_test(DisallowedCommands)
+add_RunCMake_test(discover_tests)
if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja|FASTBuild")
add_RunCMake_test(ExportCompileCommands)
endif()
@@ -536,6 +542,11 @@
add_RunCMake_test(GenEx-FILE_SET_PROPERTY)
add_RunCMake_test(GenEx-TARGET_PROPERTY)
add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS)
+list(LENGTH CMAKE_OSX_ARCHITECTURES _num_archs)
+if(NOT (XCODE AND _num_archs GREATER 1))
+ add_RunCMake_test(GenEx-TARGET_OBJECTS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
+ set_property(TEST RunCMake.GenEx-TARGET_OBJECTS APPEND PROPERTY LABELS "CUDA")
+endif()
add_RunCMake_test(GenEx-STRING)
add_RunCMake_test(GenEx-PATH)
add_RunCMake_test(GenEx-PATH_EQUAL)
@@ -611,6 +622,10 @@
add_RunCMake_test(TargetArtifacts -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
add_RunCMake_test(TargetObjects)
add_RunCMake_test(TargetProperties)
+add_RunCMake_test(FileSetProperties)
+add_RunCMake_test(FileSet-SOURCES -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
+ -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION}
+ -DMSVC_VERSION=${MSVC_VERSION})
add_RunCMake_test(ToolchainFile)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
@@ -637,6 +652,8 @@
add_RunCMake_test(CompileFeatures -DCMake_NO_C_STANDARD=${CMake_NO_C_STANDARD} -DCMake_NO_CXX_STANDARD=${CMake_NO_CXX_STANDARD})
add_RunCMake_test(Policy)
add_RunCMake_test(PolicyScope)
+add_RunCMake_test(Diagnostics)
+add_RunCMake_test(DiagnosticScope)
add_RunCMake_test(WriteBasicConfigVersionFile)
add_RunCMake_test(WriteCompilerDetectionHeader)
add_RunCMake_test(SourceProperties)
@@ -688,6 +705,9 @@
if(DEFINED CMake_TEST_LOCALE_CHARSET)
list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_LOCALE_CHARSET=${CMake_TEST_LOCALE_CHARSET})
endif()
+if(DEFINED CMake_TEST_LOCALE_C_UTF8)
+ list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_LOCALE_C_UTF8=${CMake_TEST_LOCALE_C_UTF8})
+endif()
if(CMake_TEST_MSYSTEM_PREFIX)
list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_MSYSTEM_PREFIX=${CMake_TEST_MSYSTEM_PREFIX})
endif()
@@ -769,6 +789,9 @@
add_RunCMake_test(include_guard)
add_RunCMake_test(list)
add_RunCMake_test(load_cache)
+if(DEFINED CMake_TEST_MATH_OVERFLOW)
+ list(APPEND math_ARGS -DCMake_TEST_MATH_OVERFLOW=${CMake_TEST_MATH_OVERFLOW})
+endif()
add_RunCMake_test(math)
add_RunCMake_test(message)
add_RunCMake_test(option)
@@ -999,7 +1022,11 @@
add_RunCMake_test(LinkLibrariesProcessing)
add_RunCMake_test(LinkLibrariesStrategy)
add_RunCMake_test(LinkFlags -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
-add_RunCMake_test(File_Archive -DPython_EXECUTABLE=${Python_EXECUTABLE})
+if(DEFINED CMake_TEST_LOCALE_CHARSET)
+ list(APPEND File_Archive_ARGS -DCMake_TEST_LOCALE_CHARSET=${CMake_TEST_LOCALE_CHARSET})
+endif()
+list(APPEND File_Archive_ARGS -DPython_EXECUTABLE=${Python_EXECUTABLE})
+add_RunCMake_test(File_Archive)
add_RunCMake_test(File_Configure)
add_RunCMake_test(File_Generate)
add_RunCMake_test(ExportWithoutLanguage)
@@ -1096,6 +1123,9 @@
if(CMake_TEST_LibArchive_VERSION)
list(APPEND CommandLineTar_ARGS -DCMake_TEST_LibArchive_VERSION=${CMake_TEST_LibArchive_VERSION})
endif()
+if(DEFINED CMake_TEST_LOCALE_CHARSET)
+ list(APPEND CommandLineTar_ARGS -DCMake_TEST_LOCALE_CHARSET=${CMake_TEST_LOCALE_CHARSET})
+endif()
list(APPEND CommandLineTar_ARGS -DPython_EXECUTABLE=${Python_EXECUTABLE})
add_RunCMake_test(CommandLineTar)
@@ -1496,7 +1526,7 @@
-DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}
)
-add_RunCMake_test(VerifyHeaderSets)
+add_RunCMake_test(VerifyHeaderSets -DCMake_TEST_OBJC=${CMake_TEST_OBJC})
add_RunCMake_test(set_tests_properties)
add_RunCMake_test(CMakeListFileName)
diff --git a/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt
index 57b714d..b3cda37 100644
--- a/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"default" ?- Default Config
"ninja-multi" ?- Ninja Multi-Config(
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported-stderr.txt
new file mode 100644
index 0000000..b75a5d6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported:
+File version must be 12 or higher for errors\.author support$
diff --git a/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported.json.in b/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported.json.in
new file mode 100644
index 0000000..11b36bc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorAuthorNotSupported.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 11,
+ "configurePresets": [
+ {
+ "name": "ErrorAuthorNotSupported",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "errors": {
+ "author": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt
index f76478c..4537246 100644
--- a/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt
@@ -5,4 +5,12 @@
[^
]*/Tests/RunCMake/CMakePresets/ErrorDev\.cmake:[0-9]+ \(include\)
CMakeLists\.txt:[0-9]+ \(include\)
-This error is for project developers\. Use -Wno-error=dev to suppress it\.$
+This error is for project developers\. Use -Wno-error=dev to suppress it\.
+
+CMake Deprecation Error at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Deprecation warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/ErrorDev\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/ErrorDevNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/ErrorDevNotSupported-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ErrorDevNotSupported-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorDevNotSupported-stderr.txt
new file mode 100644
index 0000000..7111cb7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDevNotSupported-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorDevNotSupported:
+File version must be 11 or lower for errors\.dev support$
diff --git a/Tests/RunCMake/CMakePresets/ErrorDevNotSupported.json.in b/Tests/RunCMake/CMakePresets/ErrorDevNotSupported.json.in
new file mode 100644
index 0000000..b2a6df2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDevNotSupported.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 12,
+ "configurePresets": [
+ {
+ "name": "ErrorDevNotSupported",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "errors": {
+ "dev": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ErrorUninitialized-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorUninitialized-stderr.txt
new file mode 100644
index 0000000..dd4430f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUninitialized-stderr.txt
@@ -0,0 +1,5 @@
+CMake Warning:
+ Manually-specified variables were not used by the project:
+
+ RunCMake_GENERATOR
+ UNUSED_VARIABLE$
diff --git a/Tests/RunCMake/CMakePresets/ErrorUninitialized.cmake b/Tests/RunCMake/CMakePresets/ErrorUninitialized.cmake
new file mode 100644
index 0000000..12a28a5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUninitialized.cmake
@@ -0,0 +1,6 @@
+cmake_diagnostic(GET CMD_UNINITIALIZED action)
+if(NOT "${action}" STREQUAL SEND_ERROR)
+ message(SEND_ERROR
+ "wrong action for diagnostic CMD_UNINITIALIZED"
+ " (expected 'SEND_ERROR', actual '${action}')")
+endif()
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported-stderr.txt
new file mode 100644
index 0000000..9646315
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported:
+File version must be 12 or higher for errors\.uninitialized support$
diff --git a/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported.json.in b/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported.json.in
new file mode 100644
index 0000000..0f4ce21
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUninitializedNotSupported.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 11,
+ "configurePresets": [
+ {
+ "name": "ErrorUninitializedNotSupported",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "errors": {
+ "uninitialized": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/ErrorUnusedCli-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/ErrorUnusedCli-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ErrorUnusedCli-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorUnusedCli-stderr.txt
new file mode 100644
index 0000000..0b479ff
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUnusedCli-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error:
+ Manually-specified variables were not used by the project:
+
+ RunCMake_GENERATOR
+ UNUSED_VARIABLE
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMakePresets/ErrorUnusedCli.cmake b/Tests/RunCMake/CMakePresets/ErrorUnusedCli.cmake
new file mode 100644
index 0000000..a4dd3ba
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUnusedCli.cmake
@@ -0,0 +1,6 @@
+cmake_diagnostic(GET CMD_UNUSED_CLI action)
+if(NOT "${action}" STREQUAL SEND_ERROR)
+ message(SEND_ERROR
+ "wrong action for diagnostic CMD_UNUSED_CLI"
+ " (expected 'SEND_ERROR', actual '${action}')")
+endif()
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported-stderr.txt
new file mode 100644
index 0000000..07d3a13
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported:
+File version must be 12 or higher for errors\.unusedCli support$
diff --git a/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported.json.in b/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported.json.in
new file mode 100644
index 0000000..83c2964
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorUnusedCliNotSupported.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 11,
+ "configurePresets": [
+ {
+ "name": "ErrorUnusedCliNotSupported",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "errors": {
+ "unusedCli": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/FileDir.cmake b/Tests/RunCMake/CMakePresets/FileDir.cmake
deleted file mode 100644
index c7298cd..0000000
--- a/Tests/RunCMake/CMakePresets/FileDir.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
-
-test_variable(TEST_FILE_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}/subdir")
diff --git a/Tests/RunCMake/CMakePresets/FileDir.json.in b/Tests/RunCMake/CMakePresets/FileDir.json.in
index 899e5f3..b741853 100644
--- a/Tests/RunCMake/CMakePresets/FileDir.json.in
+++ b/Tests/RunCMake/CMakePresets/FileDir.json.in
@@ -1,6 +1,15 @@
{
"version": 4,
"include": [
- "subdir/FileDir.json"
+ "@FileDir_include_subdir@"
+ ],
+ "configurePresets": [
+ {
+ "name": "FileDirExt",
+ "inherits": "FileDir",
+ "cacheVariables": {
+ "PRESET": "FileDirExt"
+ }
+ }
]
}
diff --git a/Tests/RunCMake/CMakePresets/FileDirv12.cmake b/Tests/RunCMake/CMakePresets/FileDirv12.cmake
new file mode 100644
index 0000000..04fb6e9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/FileDirv12.cmake
@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+if(NOT "${PRESET}" STREQUAL "FileDirInclude")
+ test_variable(CMAKE_BINARY_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}/subdir/build")
+ test_variable(TEST_FILE_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}/subdir")
+endif()
diff --git a/Tests/RunCMake/CMakePresets/FileDirv4.cmake b/Tests/RunCMake/CMakePresets/FileDirv4.cmake
new file mode 100644
index 0000000..32f516c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/FileDirv4.cmake
@@ -0,0 +1,9 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+if (PRESET STREQUAL "FileDir")
+ test_variable(CMAKE_BINARY_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}/subdir/build")
+ test_variable(TEST_FILE_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}/subdir")
+elseif (PRESET STREQUAL "FileDirExt")
+ test_variable(CMAKE_BINARY_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}/build")
+ test_variable(TEST_FILE_DIR "" "${CMAKE_CURRENT_SOURCE_DIR}")
+endif()
diff --git a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
index ba962b4..4a9f6e4 100644
--- a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/HighVersion:
-CMakePresets\.json:2: Unrecognized "version" 1000: must be >=1 and <=11
+CMakePresets\.json:2: Unrecognized "version" 1000: must be >=1 and <=12
"version": 1000,
\^$
diff --git a/Tests/RunCMake/CMakePresets/Include-stdout.txt b/Tests/RunCMake/CMakePresets/Include-stdout.txt
index 6ba1170..e256057 100644
--- a/Tests/RunCMake/CMakePresets/Include-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/Include-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"IncludeUser"
"IncludeUserCommon"
diff --git a/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt b/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt
index d3f1afc..facf2b6 100644
--- a/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"Include"
"IncludeCommon"$
diff --git a/Tests/RunCMake/CMakePresets/IncludeExpansionOtherMacros-stdout.txt b/Tests/RunCMake/CMakePresets/IncludeExpansionOtherMacros-stdout.txt
index d3f1afc..facf2b6 100644
--- a/Tests/RunCMake/CMakePresets/IncludeExpansionOtherMacros-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/IncludeExpansionOtherMacros-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"Include"
"IncludeCommon"$
diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt
index 5d978bf..96346d5 100644
--- a/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"default"
diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt
index 71ce24a..2bf40c5 100644
--- a/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"default"
diff --git a/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt
index 97eedae..ae4188a 100644
--- a/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
index 97eedae..ae4188a 100644
--- a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
index 97eedae..ae4188a 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
index 97eedae..ae4188a 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
index 97eedae..ae4188a 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
@@ -1,5 +1,4 @@
-^Not searching for unused variables given on the command line\.
-Available configure presets:
+^Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
index 5ed2857..880058f 100644
--- a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/LowVersion:
-CMakePresets\.json:2: Unrecognized "version" 0: must be >=1 and <=11
+CMakePresets\.json:2: Unrecognized "version" 0: must be >=1 and <=12
"version": 0,
\^
diff --git a/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt b/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt
index cb01a02..10f3293 100644
--- a/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt
@@ -1 +1 @@
-^Not searching for unused variables given on the command line\.$
+^$
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index 6ffd7e5..e1e6ad4 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -66,7 +66,7 @@
if(CMakePresets_NO_SOURCE_ARGS)
set(_source_args)
endif()
- set(_unused_cli --no-warn-unused-cli)
+ set(_unused_cli -Wno-unused-cli)
if(CMakePresets_WARN_UNUSED_CLI)
set(_unused_cli)
endif()
@@ -174,6 +174,13 @@
run_cmake_presets(ConditionFuture)
run_cmake_presets(SubConditionNull)
run_cmake_presets(TraceNotSupported)
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
+run_cmake_presets(WarningDevNotSupported)
+run_cmake_presets(WarningAuthorNotSupported)
+run_cmake_presets(ErrorDevNotSupported)
+run_cmake_presets(ErrorAuthorNotSupported)
+run_cmake_presets(ErrorUninitializedNotSupported)
+run_cmake_presets(ErrorUnusedCliNotSupported)
set(CMakePresets_NO_PRESET 1)
set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
@@ -343,13 +350,21 @@
run_cmake_presets(ListAllPresetsNoTest --list-presets=all)
# Test warning and error flags
-set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings.json.in")
set(CMakePresets_WARN_UNUSED_CLI 1)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings.json.in")
run_cmake_presets(NoWarningFlags)
run_cmake_presets(WarningFlags)
run_cmake_presets(DisableWarningFlags)
run_cmake_presets(ErrorDev)
run_cmake_presets(ErrorDeprecated)
+
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings12.json.in")
+run_cmake_presets(NoWarningFlags)
+run_cmake_presets(WarningFlags)
+run_cmake_presets(DisableWarningFlags)
+run_cmake_presets(ErrorDev)
+run_cmake_presets(ErrorUninitialized)
+run_cmake_presets(ErrorUnusedCli)
unset(CMakePresets_WARN_UNUSED_CLI)
# Test debug
@@ -377,10 +392,20 @@
# Test ${fileDir} macro
set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/FileDir.json.in")
+set(FileDir_include_subdir "subdir/FileDirv4.json")
set(CMakePresets_EXTRA_FILES
- "${RunCMake_SOURCE_DIR}/subdir/FileDir.json.in"
- )
-run_cmake_presets(FileDir)
+ "${RunCMake_SOURCE_DIR}/${FileDir_include_subdir}.in"
+)
+run_cmake_presets(FileDirv4 --preset FileDir)
+run_cmake_presets(FileDirv4 --preset FileDirExt)
+set(FileDir_include_subdir "subdir/FileDirv12.json")
+set(CMakePresets_EXTRA_FILES
+ "${RunCMake_SOURCE_DIR}/${FileDir_include_subdir}.in"
+ "${RunCMake_SOURCE_DIR}/subdir/FileDirInclude.json.in"
+)
+run_cmake_presets(FileDirv12 --preset FileDir)
+run_cmake_presets(FileDirv12 --preset FileDirExt)
+run_cmake_presets(FileDirv12 --preset FileDirInclude)
unset(CMakePresets_EXTRA_FILES)
set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/FileDirFuture.json.in")
run_cmake_presets(FileDirFuture)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/WarningAuthorNotSupported-result.txt
diff --git a/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported-stderr.txt b/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported-stderr.txt
new file mode 100644
index 0000000..4dc87b4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported:
+File version must be 12 or higher for warnings\.author support$
diff --git a/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported.json.in b/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported.json.in
new file mode 100644
index 0000000..03a3656
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningAuthorNotSupported.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 11,
+ "configurePresets": [
+ {
+ "name": "WarningAuthorNotSupported",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "warnings": {
+ "author": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresets/WarningDevNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresets/WarningDevNotSupported-result.txt
diff --git a/Tests/RunCMake/CMakePresets/WarningDevNotSupported-stderr.txt b/Tests/RunCMake/CMakePresets/WarningDevNotSupported-stderr.txt
new file mode 100644
index 0000000..75f3003
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningDevNotSupported-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/WarningDevNotSupported:
+File version must be 11 or lower for warnings\.dev support$
diff --git a/Tests/RunCMake/CMakePresets/WarningDevNotSupported.json.in b/Tests/RunCMake/CMakePresets/WarningDevNotSupported.json.in
new file mode 100644
index 0000000..32c6198
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningDevNotSupported.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 12,
+ "configurePresets": [
+ {
+ "name": "WarningDevNotSupported",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "warnings": {
+ "dev": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/Warnings12.json.in b/Tests/RunCMake/CMakePresets/Warnings12.json.in
new file mode 100644
index 0000000..64eae5d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Warnings12.json.in
@@ -0,0 +1,70 @@
+{
+ "version": 12,
+ "configurePresets": [
+ {
+ "name": "NoWarningFlags",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "UNUSED_VARIABLE": "Unused"
+ }
+ },
+ {
+ "name": "WarningFlags",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "author": true,
+ "deprecated": true,
+ "uninitialized": true,
+ "unusedCli": false,
+ "systemVars": true
+ }
+ },
+ {
+ "name": "DisableWarningFlags",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "author": false,
+ "deprecated": false,
+ "unusedCli": false
+ }
+ },
+ {
+ "name": "ErrorDev",
+ "inherits": "NoWarningFlags",
+ "errors": {
+ "author": true
+ }
+ },
+ {
+ "name": "ErrorDeprecated",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "author": false
+ },
+ "errors": {
+ "deprecated": true
+ }
+ },
+ {
+ "name": "ErrorUninitialized",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "author": false
+ },
+ "errors": {
+ "uninitialized": true
+ }
+ },
+ {
+ "name": "ErrorUnusedCli",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "author": false
+ },
+ "errors": {
+ "unusedCli": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/subdir/FileDir.json.in b/Tests/RunCMake/CMakePresets/subdir/FileDir.json.in
deleted file mode 100644
index 00282a7..0000000
--- a/Tests/RunCMake/CMakePresets/subdir/FileDir.json.in
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version": 4,
- "configurePresets": [
- {
- "name": "FileDir",
- "generator": "@RunCMake_GENERATOR@",
- "binaryDir": "${sourceDir}/build",
- "cacheVariables": {
- "TEST_FILE_DIR": "${fileDir}"
- }
- }
- ]
-}
diff --git a/Tests/RunCMake/CMakePresets/subdir/FileDirInclude.json.in b/Tests/RunCMake/CMakePresets/subdir/FileDirInclude.json.in
new file mode 100644
index 0000000..f7dd597
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/subdir/FileDirInclude.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 9,
+ "configurePresets": [
+ {
+ "name": "FileDirInclude",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${fileDir}/build",
+ "cacheVariables": {
+ "PRESET": "FileDirInclude"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/subdir/FileDirv12.json.in b/Tests/RunCMake/CMakePresets/subdir/FileDirv12.json.in
new file mode 100644
index 0000000..ed20764
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/subdir/FileDirv12.json.in
@@ -0,0 +1,17 @@
+{
+ "version": 12,
+ "include": [
+ "${fileDir}/FileDirInclude.json"
+ ],
+ "configurePresets": [
+ {
+ "name": "FileDir",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${fileDir}/build",
+ "cacheVariables": {
+ "TEST_FILE_DIR": "${fileDir}",
+ "PRESET": "FileDir"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/subdir/FileDirv4.json.in b/Tests/RunCMake/CMakePresets/subdir/FileDirv4.json.in
new file mode 100644
index 0000000..e055c4e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/subdir/FileDirv4.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 4,
+ "configurePresets": [
+ {
+ "name": "FileDir",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${fileDir}/build",
+ "cacheVariables": {
+ "TEST_FILE_DIR": "${fileDir}",
+ "PRESET": "FileDir"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsNoArg-build-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsBuild/PresetsNoArg-build-result.txt
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsNoArg-build-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsNoArg-build-stderr.txt
new file mode 100644
index 0000000..aa348ab
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/PresetsNoArg-build-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsNoArgEq-build-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsBuild/PresetsNoArgEq-build-result.txt
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsNoArgEq-build-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsNoArgEq-build-stderr.txt
new file mode 100644
index 0000000..aa348ab
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/PresetsNoArgEq-build-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset
diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
index 63dc4f3..5479343 100644
--- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
@@ -75,6 +75,8 @@
run_cmake_build_presets(Condition "default" "enabled;disabled" "")
set(CMakePresetsBuild_BUILD_ONLY 1)
+run_cmake_command(PresetsNoArg-build ${CMAKE_COMMAND} "--build" "--preset")
+run_cmake_command(PresetsNoArgEq-build ${CMAKE_COMMAND} "--build" "--preset=")
run_cmake_build_presets(ListPresets "x" "x" "--list-presets" "")
run_cmake_build_presets(NoConfigurePreset "x" "noConfigurePreset" "")
run_cmake_build_presets(Invalid "x" "hidden;vendorMacro" "")
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsPackage/PresetsNoArg-package-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsPackage/PresetsNoArg-package-result.txt
diff --git a/Tests/RunCMake/CMakePresetsPackage/PresetsNoArg-package-stderr.txt b/Tests/RunCMake/CMakePresetsPackage/PresetsNoArg-package-stderr.txt
new file mode 100644
index 0000000..aef30d2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/PresetsNoArg-package-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsPackage/PresetsNoArgEq-package-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsPackage/PresetsNoArgEq-package-result.txt
diff --git a/Tests/RunCMake/CMakePresetsPackage/PresetsNoArgEq-package-stderr.txt b/Tests/RunCMake/CMakePresetsPackage/PresetsNoArgEq-package-stderr.txt
new file mode 100644
index 0000000..aef30d2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/PresetsNoArgEq-package-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset$
diff --git a/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake
index 269fb6e..969fda2 100644
--- a/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake
@@ -100,3 +100,6 @@
run_cmake_package_presets(UnsupportedVersion "x" "" "")
run_cmake_package_presets(Good "default" "build-default-debug" "no-environment;with-environment;generators;configurations;variables;config-file;debug;verbose;package-name;package-version;package-directory;vendor-name")
run_cmake_package_presets(ListPresets "default" "" "x" "--list-presets")
+
+run_cmake_command(PresetsNoArg-package ${CMAKE_CPACK_COMMAND} "--preset")
+run_cmake_command(PresetsNoArgEq-package ${CMAKE_CPACK_COMMAND} "--preset=")
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt
index c281c81..04da40e 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt
@@ -2,4 +2,4 @@
]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
Start 6: debug-only
.*
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt
index 66bfd22..e18be0d 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt
@@ -2,4 +2,4 @@
]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
Start 6: release-only
.*
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt
index 5e990de..35cf4d6 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt
@@ -4,4 +4,4 @@
.*
Start 4: testd
.*
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt
index 2df6fcb..44de61c 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt
@@ -4,4 +4,4 @@
.*
Start 3: testc
.*
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt
index 1366876..71a36e2 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt
@@ -4,4 +4,4 @@
.*
Start 4: testd
.*
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-jobsProc-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-jobsProc-stdout.txt
index c59dcd3..cb578ed 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-jobsProc-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-jobsProc-stdout.txt
@@ -1,4 +1,4 @@
Test project [^
]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
.*
-100% tests passed, 0 tests failed out of 5
+100% tests passed out of 5
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt
index 8b4845e..da768cd 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt
@@ -5,4 +5,4 @@
.*
5: TEST_ENV_REF=xx
.*
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough-test-basic-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-basic-stdout.txt
new file mode 100644
index 0000000..e600e4c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-basic-stdout.txt
@@ -0,0 +1,3 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "--extra-flag"
+.*
diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough-test-execOnly-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-execOnly-stdout.txt
new file mode 100644
index 0000000..93e76d0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-execOnly-stdout.txt
@@ -0,0 +1,3 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "--only-arg"
+.*
diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough-test-inherit-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-inherit-stdout.txt
new file mode 100644
index 0000000..5788920
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-inherit-stdout.txt
@@ -0,0 +1,3 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "--parent-arg"
+.*
diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough.cmake b/Tests/RunCMake/CMakePresetsTest/Passthrough.cmake
new file mode 100644
index 0000000..a398f9e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Passthrough.cmake
@@ -0,0 +1,2 @@
+enable_testing()
+add_test(echo_test ${CMAKE_COMMAND} -E echo base_output)
diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough.json.in b/Tests/RunCMake/CMakePresetsTest/Passthrough.json.in
new file mode 100644
index 0000000..6fe7ac2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Passthrough.json.in
@@ -0,0 +1,47 @@
+{
+ "version": 12,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "basic",
+ "configurePreset": "default",
+ "output": {
+ "verbosity": "verbose"
+ },
+ "execution": {
+ "testPassthroughArguments": ["--extra-flag"]
+ }
+ },
+ {
+ "name": "parent",
+ "hidden": true,
+ "execution": {
+ "testPassthroughArguments": ["--parent-arg"]
+ }
+ },
+ {
+ "name": "inherit",
+ "inherits": "parent",
+ "configurePreset": "default",
+ "output": {
+ "verbosity": "verbose"
+ }
+ },
+ {
+ "name": "execOnly",
+ "configurePreset": "default",
+ "output": {
+ "verbosity": "verbose"
+ },
+ "execution": {
+ "testPassthroughArguments": ["--only-arg"]
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughCombined-test-combined-stdout.txt b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined-test-combined-stdout.txt
new file mode 100644
index 0000000..e572da9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined-test-combined-stdout.txt
@@ -0,0 +1,3 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "--preset-arg" "--cli-arg"
+.*
diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.cmake b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.cmake
new file mode 100644
index 0000000..a398f9e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.cmake
@@ -0,0 +1,2 @@
+enable_testing()
+add_test(echo_test ${CMAKE_COMMAND} -E echo base_output)
diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.json.in b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.json.in
new file mode 100644
index 0000000..37beede
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.json.in
@@ -0,0 +1,22 @@
+{
+ "version": 12,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "combined",
+ "configurePreset": "default",
+ "output": {
+ "verbosity": "verbose"
+ },
+ "execution": {
+ "testPassthroughArguments": ["--preset-arg"]
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-stderr.txt
new file mode 100644
index 0000000..a3aaf4f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported:
+File version must be 12 or higher for testPassthroughArguments preset support$
diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported.json.in
new file mode 100644
index 0000000..c6edbcc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported.json.in
@@ -0,0 +1,19 @@
+{
+ "version": 11,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "execution": {
+ "testPassthroughArguments": ["--extra"]
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsTest/PresetsNoArg-test-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsTest/PresetsNoArg-test-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsNoArg-test-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PresetsNoArg-test-stderr.txt
new file mode 100644
index 0000000..c477131
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PresetsNoArg-test-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: '--preset' requires an argument$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsTest/PresetsNoArgEq-test-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsTest/PresetsNoArgEq-test-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsNoArgEq-test-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PresetsNoArgEq-test-stderr.txt
new file mode 100644
index 0000000..c477131
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PresetsNoArgEq-test-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: '--preset' requires an argument$
diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
index d7fcb48..42dfe18 100644
--- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
@@ -95,6 +95,9 @@
set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Good.json.in")
run_cmake_test_presets(ListPresets "" "" "x" "--list-presets")
+run_cmake_command(PresetsNoArg-test ${CMAKE_CTEST_COMMAND} "--preset")
+run_cmake_command(PresetsNoArgEq-test ${CMAKE_CTEST_COMMAND} "--preset=")
+
set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Condition.json.in")
run_cmake_test_presets(ConditionListPresets "" "" "x" "--list-presets")
unset(CMakePresetsTest_NO_CONFIGURE)
@@ -113,8 +116,13 @@
run_cmake_test_presets(OutputJUnitUnsupported "" "" "x")
run_cmake_test_presets(InvalidJobs "" "" "x")
run_cmake_test_presets(JobsProcUnsupported "" "" "x")
+run_cmake_test_presets(PassthroughUnsupported "" "" "x")
set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
run_cmake_test_presets(ConfigurePresetUnreachable "" "" "x")
set(CMakePresetsTest_NO_CONFIGURE 0)
+run_cmake_test_presets(Passthrough "default" "" "basic;inherit;execOnly")
+run_cmake_test_presets(PassthroughCombined "default" "" "combined" "--" "--cli-arg")
+set(CMakePresetsTest_NO_CONFIGURE 1)
+
set(CMakePresetsTest_NO_BUILD 0)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArg-workflow-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArg-workflow-result.txt
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArg-workflow-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArg-workflow-stderr.txt
new file mode 100644
index 0000000..aa348ab
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArg-workflow-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArgEq-workflow-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArgEq-workflow-result.txt
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArgEq-workflow-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArgEq-workflow-stderr.txt
new file mode 100644
index 0000000..aa348ab
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/PresetsNoArgEq-workflow-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake
index 8c1002d..fac8dfc 100644
--- a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake
@@ -81,6 +81,8 @@
unset(CMakePresets_ASSETS)
run_cmake_workflow_presets(ListPresets --list-presets)
+run_cmake_command(PresetsNoArg-workflow ${CMAKE_COMMAND} "--workflow" "--preset")
+run_cmake_command(PresetsNoArgEq-workflow ${CMAKE_COMMAND} "--workflow" "--preset=")
run_cmake_workflow_presets(InvalidOption -DINVALID_OPTION)
set(RunCMake_TEST_NO_CLEAN TRUE)
diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake b/Tests/RunCMake/CPack/DEB/Helpers.cmake
index 7471446..3e9cc9d 100644
--- a/Tests/RunCMake/CPack/DEB/Helpers.cmake
+++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake
@@ -145,13 +145,14 @@
" Content: '${content_}'")
endif()
- execute_process(COMMAND ls -l "${CMAKE_CURRENT_BINARY_DIR}/control_${PREFIX}/${FILE_}"
- OUTPUT_VARIABLE package_permissions_
- ERROR_VARIABLE package_permissions_error_
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
+ execute_process(
+ COMMAND stat --format=%A "${CMAKE_CURRENT_BINARY_DIR}/control_${PREFIX}/${FILE_}"
+ OUTPUT_VARIABLE package_permissions_
+ ERROR_VARIABLE package_permissions_error_
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
if(NOT package_permissions_error_)
- if(NOT package_permissions_ MATCHES "${${PREFIX}_${FILE_}_permissions_regex}")
+ if(NOT package_permissions_ STREQUAL ${PREFIX}_${FILE_}_permissions)
message(FATAL_ERROR "Unexpected file permissions for ${PREFIX}_${FILE_}: '${package_permissions_}'!")
endif()
else()
diff --git a/Tests/RunCMake/CPack/TAR/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/TAR/packaging_COMPONENT_default.cmake
index 81a5035..a6801f3 100644
--- a/Tests/RunCMake/CPack/TAR/packaging_COMPONENT_default.cmake
+++ b/Tests/RunCMake/CPack/TAR/packaging_COMPONENT_default.cmake
@@ -1 +1,2 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON")
+set(CPACK_ARCHIVE_ENCODING "OEM")
diff --git a/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake
index 81a5035..a6801f3 100644
--- a/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake
+++ b/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake
@@ -1 +1,2 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON")
+set(CPACK_ARCHIVE_ENCODING "OEM")
diff --git a/Tests/RunCMake/CPack/ZIP_DEFLATE/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/ZIP_DEFLATE/packaging_COMPONENT_default.cmake
index 2a57279..e1f8e70 100644
--- a/Tests/RunCMake/CPack/ZIP_DEFLATE/packaging_COMPONENT_default.cmake
+++ b/Tests/RunCMake/CPack/ZIP_DEFLATE/packaging_COMPONENT_default.cmake
@@ -1,2 +1,3 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON")
set(CPACK_ARCHIVE_COMPRESSION_LEVEL 4)
+set(CPACK_ARCHIVE_ENCODING "UTF-8")
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/VerifyResult.cmake
new file mode 100644
index 0000000..20b20c8
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/VerifyResult.cmake
@@ -0,0 +1,27 @@
+cmake_path(APPEND bin_dir _CPack_Packages/Linux/RPM/SPECS OUTPUT_VARIABLE SPECS)
+
+file(GLOB specs "${SPECS}/*.spec")
+if(NOT specs)
+ return()
+endif()
+
+set(_pfx multilene_defines_test)
+set(
+ expected_defines
+ "%define ${_pfx}_satu 1"
+ "%define ${_pfx}_dua 2"
+ "%define ${_pfx}_tiga 3"
+ )
+
+foreach(spec IN LISTS specs)
+ file(STRINGS "${spec}" defines REGEX "%define multilene_defines_test_*.")
+ if(NOT defines STREQUAL expected_defines)
+ message(
+ FATAL_ERROR
+ "Multiline definitions mismatch:\n"
+ " file: `${spec}`\n"
+ " expected: `${expected_defines}`\n"
+ " actual: `${defines}`\n"
+ )
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake
index a604863..da5f6fc 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake
@@ -1,5 +1,10 @@
install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
+set(_pfx multilene_defines_test)
+set(CPACK_RPM_SPEC_MORE_DEFINE "%define ${_pfx}_satu 1")
+list(APPEND CPACK_RPM_SPEC_MORE_DEFINE "%define ${_pfx}_dua 2")
+list(APPEND CPACK_RPM_SPEC_MORE_DEFINE "%define ${_pfx}_tiga 3")
+
if(PACKAGING_TYPE STREQUAL "MONOLITHIC")
set(CPACK_RPM_USER_BINARY_SPECFILE "${CMAKE_CURRENT_LIST_DIR}/custom.spec.in")
elseif(PACKAGING_TYPE STREQUAL "COMPONENT")
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/VerifyResult.cmake
new file mode 100644
index 0000000..5ef05a3
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/VerifyResult.cmake
@@ -0,0 +1,19 @@
+if(NOT GENERATOR_TYPE STREQUAL "DEB")
+ return()
+endif()
+
+set(whitespaces_ "[\t\n\r ]*")
+set(hashsyms_ "[a-f0-9]+")
+
+set(dbgsym_md5sums_md5sums
+ "^(${hashsyms_} usr/lib/debug/\\.build-id/[^/\r\n]+/[^/\r\n]+\\.debug${whitespaces_})+$")
+set(dbgsym_md5sums_md5sums_permissions "-rw-r--r--")
+
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+ verifyDebControl("${FOUND_FILE_4}" "dbgsym_md5sums" "md5sums")
+ verifyDebControl("${FOUND_FILE_5}" "dbgsym_md5sums" "md5sums")
+
+elseif(PACKAGING_TYPE STREQUAL "MONOLITHIC")
+ verifyDebControl("${FOUND_FILE_2}" "dbgsym_md5sums" "md5sums")
+
+endif()
diff --git a/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_file-stderr.txt b/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_file-stderr.txt
index 5544885..003c396 100644
--- a/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_file-stderr.txt
+++ b/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_file-stderr.txt
@@ -1 +1 @@
-CPack Error: ERROR The data in files with the same filename is different.*
+CPack Error: ERROR The data in files with the same filename is different: files/1\.txt
diff --git a/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_symlink-stderr.txt b/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_symlink-stderr.txt
index 5544885..ac23e71 100644
--- a/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_symlink-stderr.txt
+++ b/Tests/RunCMake/CPack/tests/DUPLICATE_FILE/conflict_symlink-stderr.txt
@@ -1 +1 @@
-CPack Error: ERROR The data in files with the same filename is different.*
+CPack Error: ERROR The data in files with the same filename is different: files/symlink2
diff --git a/Tests/RunCMake/CPack/tests/EXTRA/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/EXTRA/VerifyResult.cmake
index 85e137f..1dd1a75 100644
--- a/Tests/RunCMake/CPack/tests/EXTRA/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/EXTRA/VerifyResult.cmake
@@ -1,18 +1,18 @@
set(foo_preinst "^echo default_preinst$")
# NOTE: optional dot at the end of permissions regex is for SELinux enabled systems
-set(foo_preinst_permissions_regex "-rwxr-xr-x\.? .*")
+set(foo_preinst_permissions "-rwxr-xr-x")
set(foo_prerm "^echo default_prerm$")
-set(foo_prerm_permissions_regex "-rwxr-xr-x\.? .*")
+set(foo_prerm_permissions "-rwxr-xr-x")
verifyDebControl("${FOUND_FILE_1}" "foo" "preinst;prerm")
set(bar_preinst "^echo bar_preinst$")
-set(bar_preinst_permissions_regex "-rwx------\.? .*")
+set(bar_preinst_permissions "-rwx------")
set(bar_prerm "^echo bar_prerm$")
-set(bar_prerm_permissions_regex "-rwx------\.? .*")
+set(bar_prerm_permissions "-rwx------")
verifyDebControl("${FOUND_FILE_2}" "bar" "preinst;prerm")
set(bas_preinst "^echo default_preinst$")
-set(bas_preinst_permissions_regex "-rwxr-xr-x\.? .*")
+set(bas_preinst_permissions "-rwxr-xr-x")
set(bas_prerm "^echo default_prerm$")
-set(bas_prerm_permissions_regex "-rwxr-xr-x\.? .*")
+set(bas_prerm_permissions "-rwxr-xr-x")
verifyDebControl("${FOUND_FILE_3}" "bas" "preinst;prerm")
diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake
index 8cefeea..894b27c 100644
--- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake
@@ -5,5 +5,5 @@
endif()
# optional dot at the end of permissions regex is for SELinux enabled systems
-set(shlibs_shlibs_permissions_regex "-rw-r--r--\.? .*")
+set(shlibs_shlibs_permissions "-rw-r--r--")
verifyDebControl("${FOUND_FILE_1}" "shlibs" "shlibs")
diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/VerifyResult.cmake
index 422cfbe..edb1846 100644
--- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/VerifyResult.cmake
@@ -1,8 +1,37 @@
+find_program(DPKG_EXECUTABLE dpkg)
+set(_dpkg_is_old FALSE)
+if(DPKG_EXECUTABLE)
+ execute_process(
+ COMMAND "${DPKG_EXECUTABLE}" --version
+ OUTPUT_VARIABLE DPKG_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ set(_dpkg_version_re "Debian 'dpkg' package management program version ([0-9]+\.[0-9]+\.[0-9]+).*")
+ if(DPKG_VERSION MATCHES "${_dpkg_version_re}")
+ set(DPKG_VERSION "${CMAKE_MATCH_1}")
+ if(DPKG_VERSION VERSION_LESS 1.18.3)
+ set(_dpkg_is_old TRUE)
+ endif()
+ else()
+ set(_dpkg_is_old TRUE)
+ endif()
+else()
+ set(_dpkg_is_old TRUE)
+endif()
+
+set(expected_files shlibs)
set(shlibs_shlibs "^libtest_lib 0\\.8 generate_shlibs_ldconfig \\(>\\= 0\\.1\\.1\\)\n$")
-# NOTE: optional dot at the end of permissions regex is for SELinux enabled systems
-set(shlibs_shlibs_permissions_regex "-rw-r--r--\.? .*")
-set(shlibs_postinst ".*ldconfig.*")
-set(shlibs_postinst_permissions_regex "-rwxr-xr-x\.? .*")
-set(shlibs_postrm ".*ldconfig.*")
-set(shlibs_postrm_permissions_regex "-rwxr-xr-x\.? .*")
-verifyDebControl("${FOUND_FILE_1}" "shlibs" "shlibs;postinst;postrm")
+set(shlibs_shlibs_permissions "-rw-r--r--")
+if(_dpkg_is_old)
+ list(APPEND expected_files postinst postrm)
+ set(shlibs_postinst ".*ldconfig.*")
+ set(shlibs_postinst_permissions "-rwxr-xr-x")
+
+ set(shlibs_postrm ".*ldconfig.*")
+ set(shlibs_postrm_permissions "-rwxr-xr-x")
+else()
+ list(APPEND expected_files triggers)
+ set(shlibs_triggers ".*activate-noawait ldconfig.*")
+ set(shlibs_triggers_permissions "-rw-r--r--")
+endif()
+verifyDebControl("${FOUND_FILE_1}" "shlibs" "${expected_files}")
diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake
index 13af097..8b12e57 100644
--- a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake
@@ -1,4 +1,5 @@
set(whitespaces_ "[\t\n\r ]*")
set(hashsyms_ "[a-f0-9]+")
set(md5sums_md5sums "^${hashsyms_} usr/bar/CMakeLists\.txt${whitespaces_}${hashsyms_} usr/baz/CMakeLists\.txt${whitespaces_}${hashsyms_} usr/foo/CMakeLists\.txt${whitespaces_}$")
+set(md5sums_md5sums_permissions "-rw-r--r--")
verifyDebControl("${FOUND_FILE_1}" "md5sums" "md5sums")
diff --git a/Tests/RunCMake/CPack/tests/MULTIARCH/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/MULTIARCH/VerifyResult.cmake
index f4e8050..1dfed5c 100644
--- a/Tests/RunCMake/CPack/tests/MULTIARCH/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/MULTIARCH/VerifyResult.cmake
@@ -1,4 +1,5 @@
if(NOT ${RunCMake_SUBTEST_SUFFIX} STREQUAL "fail")
set(MULTIARCH_control "Multi-Arch: ${RunCMake_SUBTEST_SUFFIX}")
+ set(MULTIARCH_control_permissions "-rw-r--r--")
verifyDebControl("${FOUND_FILE_1}" "MULTIARCH" "control")
endif ()
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake
index 0632319..9e57365 100644
--- a/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake
@@ -6,21 +6,18 @@
file(GLOB_RECURSE symlink_files RELATIVE "${bin_dir}" "${bin_dir}/*/symlink_*")
foreach(check_symlink IN LISTS symlink_files)
- get_filename_component(symlink_name "${check_symlink}" NAME)
- execute_process(COMMAND ls -la "${check_symlink}"
- WORKING_DIRECTORY "${bin_dir}"
- OUTPUT_VARIABLE SYMLINK_POINT_
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ cmake_path(GET check_symlink FILENAME symlink_name)
+ file(READ_SYMLINK "${check_symlink}" symlink_dst)
if("${symlink_name}" STREQUAL "symlink_to_empty_dir")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}empty_dir$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^empty_dir$" check_symlink "${symlink_dst}")
elseif("${symlink_name}" STREQUAL "symlink_to_non_empty_dir")
- string(REGEX MATCH "^.*${whitespaces}->${whitespaces}non_empty_dir$" check_symlink "${SYMLINK_POINT_}")
+ string(REGEX MATCH "^non_empty_dir$" check_symlink "${symlink_dst}")
else()
message(FATAL_ERROR "error: unexpected rpm symbolic link '${check_symlink}'")
endif()
if(NOT check_symlink)
- message(FATAL_ERROR "symlink points to unexpected location '${SYMLINK_POINT_}'")
+ message(FATAL_ERROR "symlink points to unexpected location '${symlink_dst}'")
endif()
endforeach()
diff --git a/Tests/RunCMake/CTest/SingleConfig-test-stdout.txt b/Tests/RunCMake/CTest/SingleConfig-test-stdout.txt
index 5771618..7898434 100644
--- a/Tests/RunCMake/CTest/SingleConfig-test-stdout.txt
+++ b/Tests/RunCMake/CTest/SingleConfig-test-stdout.txt
@@ -3,6 +3,6 @@
Start 1: SingleConfig
1/1 Test #1: SingleConfig .+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt
index b1851b9..24495d0 100644
--- a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt
@@ -2,6 +2,6 @@
.* +Start 1: CommandExpandList
1/1 Test #1: CommandExpandList +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/CTestCommandLine/CustomPrePost-show-only-stdout.txt b/Tests/RunCMake/CTestCommandLine/CustomPrePost-show-only-stdout.txt
new file mode 100644
index 0000000..971bc9a
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/CustomPrePost-show-only-stdout.txt
@@ -0,0 +1,5 @@
+^Test project [^
+]+/Tests/RunCMake/CTestCommandLine/CustomPrePost
+ Test #1: Echo
+
+Total Tests: 1$
diff --git a/Tests/RunCMake/CTestCommandLine/CustomPrePost-stdout.txt b/Tests/RunCMake/CTestCommandLine/CustomPrePost-stdout.txt
new file mode 100644
index 0000000..d65ee95
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/CustomPrePost-stdout.txt
@@ -0,0 +1,10 @@
+^Test project [^
+]+/Tests/RunCMake/CTestCommandLine/CustomPrePost
+Custom Pre-Test
+ Start 1: Echo
+1/1 Test #1: Echo \.+ Passed +[0-9\.]+ sec
+
+100% tests passed out of 1
+
+Total Test time \(real\) = +[0-9\.]+ sec
+Custom Post-Test$
diff --git a/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt b/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt
index 0e9f937..e3586a3 100644
--- a/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt
@@ -1,4 +1,4 @@
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
+
+Label Time Summary:
+'bar' = +[0-9\.]+ sec\*proc \(3 tests\)
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-basic-stdout.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-basic-stdout.txt
new file mode 100644
index 0000000..7888f80
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-basic-stdout.txt
@@ -0,0 +1,6 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "--extra-flag"
+.*
+2: Test command: [^
+]* "-E" "echo" "second_test" "--extra-flag"
+.*
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-empty-error-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-empty-error-result.txt
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-empty-error-stderr.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-empty-error-stderr.txt
new file mode 100644
index 0000000..3648159
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-empty-error-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: The -- option cannot be used with --build-and-test\. Use --build-options or --test-command to forward arguments\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-error-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-error-result.txt
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-error-stderr.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-error-stderr.txt
new file mode 100644
index 0000000..3648159
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-build-and-test-error-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: The -- option cannot be used with --build-and-test\. Use --build-options or --test-command to forward arguments\.$
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-ctest-flags-stdout.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-ctest-flags-stdout.txt
new file mode 100644
index 0000000..40864f2
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-ctest-flags-stdout.txt
@@ -0,0 +1,6 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "-R" "--verbose"
+.*
+2: Test command: [^
+]* "-E" "echo" "second_test" "-R" "--verbose"
+.*
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-empty-stdout.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-empty-stdout.txt
new file mode 100644
index 0000000..a835400
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-empty-stdout.txt
@@ -0,0 +1,6 @@
+1: Test command: [^
+]* "-E" "echo" "base_output"
+.*
+2: Test command: [^
+]* "-E" "echo" "second_test"
+.*
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-multiple-stdout.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-multiple-stdout.txt
new file mode 100644
index 0000000..70b0d13
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-multiple-stdout.txt
@@ -0,0 +1,6 @@
+1: Test command: [^
+]* "-E" "echo" "base_output" "--flag1" "--flag2" "value"
+.*
+2: Test command: [^
+]* "-E" "echo" "second_test" "--flag1" "--flag2" "value"
+.*
diff --git a/Tests/RunCMake/CTestCommandLine/Passthrough-with-filter-stdout.txt b/Tests/RunCMake/CTestCommandLine/Passthrough-with-filter-stdout.txt
new file mode 100644
index 0000000..084b51d
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/Passthrough-with-filter-stdout.txt
@@ -0,0 +1,8 @@
+Test project [^
+]*/Tests/RunCMake/CTestCommandLine/Passthrough-with-filter(
+|
+[^0-9][^
+]*)+
+2: Test command: [^
+]* "-E" "echo" "second_test" "--extra"
+.*
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index ede949a..a7a8575 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -424,6 +424,8 @@
endfunction()
run_stop_on_failure()
+run_cmake_command(usage ${CMAKE_CTEST_COMMAND})
+
function(run_TestAffinity)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestAffinity)
set(RunCMake_TEST_NO_CLEAN 1)
@@ -490,6 +492,22 @@
return(PROPAGATE RunCMake_TEST_FAILED)
endfunction()
+block()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomPrePost)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestCustom.cmake" "
+set(CTEST_CUSTOM_PRE_TEST \"\\\"${CMAKE_COMMAND}\\\" -E echo \\\"Custom Pre-Test\\\"\")
+set(CTEST_CUSTOM_POST_TEST \"\\\"${CMAKE_COMMAND}\\\" -E echo \\\"Custom Post-Test\\\"\")
+")
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+ add_test(Echo \"${CMAKE_COMMAND}\" -E echo)
+")
+ run_cmake_command(CustomPrePost ${CMAKE_CTEST_COMMAND})
+ run_cmake_command(CustomPrePost-show-only ${CMAKE_CTEST_COMMAND} --show-only=human)
+endblock()
+
function(run_ShowOnly)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ShowOnly)
set(RunCMake_TEST_NO_CLEAN 1)
@@ -716,3 +734,38 @@
run_cmake_command(ScheduleRandomSeed1 ${CMAKE_CTEST_COMMAND} --schedule-random --schedule-random-seed 42)
run_cmake_command(ScheduleRandomSeed2 ${CMAKE_CTEST_COMMAND} --schedule-random --schedule-random-seed 42)
endblock()
+
+function(run_PassthroughTest case)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Passthrough-${case})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+add_test(echo_test \"${CMAKE_COMMAND}\" -E echo \"base_output\")
+add_test(echo_test2 \"${CMAKE_COMMAND}\" -E echo \"second_test\")
+")
+ run_cmake_command(Passthrough-${case} ${CMAKE_CTEST_COMMAND} ${ARGN})
+endfunction()
+
+# Basic passthrough
+run_PassthroughTest(basic -V -- --extra-flag)
+# Multiple passthrough args
+run_PassthroughTest(multiple -V -- --flag1 --flag2 value)
+# Passthrough with -R filter (only echo_test2 should run)
+run_PassthroughTest(with-filter -V -R echo_test2 -- --extra)
+# Empty passthrough (bare --)
+run_PassthroughTest(empty -V --)
+# Passthrough args that look like ctest flags
+run_PassthroughTest(ctest-flags -V -- -R --verbose)
+# -- rejected with --build-and-test
+run_cmake_command(Passthrough-build-and-test-error ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ ${RunCMake_BINARY_DIR}/Passthrough-build-and-test-error/does-not-exist
+ ${RunCMake_BINARY_DIR}/Passthrough-build-and-test-error/does-not-exist
+ --build-generator "None" -- --extra-flag)
+# bare -- rejected with --build-and-test
+run_cmake_command(Passthrough-build-and-test-empty-error ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ ${RunCMake_BINARY_DIR}/Passthrough-build-and-test-empty-error/does-not-exist
+ ${RunCMake_BINARY_DIR}/Passthrough-build-and-test-empty-error/does-not-exist
+ --build-generator "None" --)
diff --git a/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-empty-stdout.txt b/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-empty-stdout.txt
index d42dde9..487dd8b 100644
--- a/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-empty-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-empty-stdout.txt
@@ -7,4 +7,4 @@
+Start 3: Test11
3/3 Test #3: Test11 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 3
+100% tests passed out of 3
diff --git a/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-stdout.txt b/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-stdout.txt
index afc683f..3d9179e 100644
--- a/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/TestsFromFile-exclude-stdout.txt
@@ -5,5 +5,5 @@
+Start 3: Test11
2/2 Test #3: Test11 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
diff --git a/Tests/RunCMake/CTestCommandLine/TestsFromFile-include-stdout.txt b/Tests/RunCMake/CTestCommandLine/TestsFromFile-include-stdout.txt
index 6231f02..06b3b0c 100644
--- a/Tests/RunCMake/CTestCommandLine/TestsFromFile-include-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/TestsFromFile-include-stdout.txt
@@ -3,5 +3,5 @@
+Start 1: Test1
1/1 Test #1: Test1 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
diff --git a/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt b/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt
index 4c21763..13bd601 100644
--- a/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt
@@ -10,6 +10,6 @@
Start 4: goodbye
4/4 Test #4: goodbye \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt
index adc5e1f..5fd974e 100644
--- a/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt
@@ -10,6 +10,6 @@
Start 4: goodbye
4/4 Test #4: goodbye \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt
index c5809a7..0853b1d 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt
@@ -17,4 +17,4 @@
]*)*
2/2 Test #[1-2]: TestLoad[1-2] \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
index c5809a7..0853b1d 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
@@ -17,4 +17,4 @@
]*)*
2/2 Test #[1-2]: TestLoad[1-2] \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-wait0-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-wait0-stdout.txt
index ef0bdd5..70c5715 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-wait0-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-wait0-stdout.txt
@@ -18,4 +18,4 @@
]*)*
2/2 Test #[1-2]: TestLoad[1-2] \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-wait1-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-wait1-stdout.txt
index 9e90b34..da5ec70 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-wait1-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-wait1-stdout.txt
@@ -18,4 +18,4 @@
]*)*
2/2 Test #[1-2]: TestLoad[1-2] \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CTestCommandLine/usage-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CTestCommandLine/usage-result.txt
diff --git a/Tests/RunCMake/CTestCommandLine/usage-stderr.txt b/Tests/RunCMake/CTestCommandLine/usage-stderr.txt
new file mode 100644
index 0000000..dd65757
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/usage-stderr.txt
@@ -0,0 +1,3 @@
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+No test configuration file found!
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
diff --git a/Tests/RunCMake/CTestCommandLine/usage-stdout.txt b/Tests/RunCMake/CTestCommandLine/usage-stdout.txt
new file mode 100644
index 0000000..db2cedc
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/usage-stdout.txt
@@ -0,0 +1,3 @@
+Usage
+
+ ctest \[options\]
diff --git a/Tests/RunCMake/CTestResourceAllocation/process_count-ctest-s-res-check.cmake b/Tests/RunCMake/CTestResourceAllocation/process_count-ctest-s-res-check.cmake
index 585c36b..727d2f4 100644
--- a/Tests/RunCMake/CTestResourceAllocation/process_count-ctest-s-res-check.cmake
+++ b/Tests/RunCMake/CTestResourceAllocation/process_count-ctest-s-res-check.cmake
@@ -1,9 +1,9 @@
verify_ctest_resources()
read_testing_file("Test.xml" _test_contents)
-if(NOT _test_contents MATCHES "\nCTEST_RESOURCE_GROUP_0=widgets")
+if(NOT _test_contents MATCHES "(>|\n)CTEST_RESOURCE_GROUP_0=widgets")
string(APPEND RunCMake_TEST_FAILED "Could not find variable CTEST_RESOURCE_GROUP_0 in test measurements\n")
endif()
-if(NOT _test_contents MATCHES "\nCTEST_RESOURCE_GROUP_0_WIDGETS=id:")
+if(NOT _test_contents MATCHES "(>|\n)CTEST_RESOURCE_GROUP_0_WIDGETS=id:")
string(APPEND RunCMake_TEST_FAILED "Could not find variable CTEST_RESOURCE_GROUP_0_WIDGETS in test measurements\n")
endif()
diff --git a/Tests/RunCMake/CTestTimeout/FlagOverridesVar-stdout.txt b/Tests/RunCMake/CTestTimeout/FlagOverridesVar-stdout.txt
index 4e30bf6..7936164 100644
--- a/Tests/RunCMake/CTestTimeout/FlagOverridesVar-stdout.txt
+++ b/Tests/RunCMake/CTestTimeout/FlagOverridesVar-stdout.txt
@@ -3,4 +3,4 @@
Start 1: TestTimeout
1/1 Test #1: TestTimeout \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[1-9][0-9\.]* sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CTestTimeout/PropertyOverridesVar-stdout.txt b/Tests/RunCMake/CTestTimeout/PropertyOverridesVar-stdout.txt
index 2d06734..888f25b 100644
--- a/Tests/RunCMake/CTestTimeout/PropertyOverridesVar-stdout.txt
+++ b/Tests/RunCMake/CTestTimeout/PropertyOverridesVar-stdout.txt
@@ -3,4 +3,4 @@
Start 1: TestTimeout
1/1 Test #1: TestTimeout \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[1-9][0-9\.]* sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CTestTimeout/ZeroOverridesFlag-stdout.txt b/Tests/RunCMake/CTestTimeout/ZeroOverridesFlag-stdout.txt
index 6f33fee..70753cc 100644
--- a/Tests/RunCMake/CTestTimeout/ZeroOverridesFlag-stdout.txt
+++ b/Tests/RunCMake/CTestTimeout/ZeroOverridesFlag-stdout.txt
@@ -3,4 +3,4 @@
Start 1: TestTimeout
1/1 Test #1: TestTimeout \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[1-9][0-9\.]* sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CTestTimeout/ZeroOverridesVar-stdout.txt b/Tests/RunCMake/CTestTimeout/ZeroOverridesVar-stdout.txt
index c66aa01..602cbda 100644
--- a/Tests/RunCMake/CTestTimeout/ZeroOverridesVar-stdout.txt
+++ b/Tests/RunCMake/CTestTimeout/ZeroOverridesVar-stdout.txt
@@ -3,4 +3,4 @@
Start 1: TestTimeout
1/1 Test #1: TestTimeout \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[1-9][0-9\.]* sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/CTestTimeoutAfterMatch/ShouldPass-stdout.txt b/Tests/RunCMake/CTestTimeoutAfterMatch/ShouldPass-stdout.txt
index 941a0fd..1d2ce21 100644
--- a/Tests/RunCMake/CTestTimeoutAfterMatch/ShouldPass-stdout.txt
+++ b/Tests/RunCMake/CTestTimeoutAfterMatch/ShouldPass-stdout.txt
@@ -1,6 +1,6 @@
Start 1: SleepFor1Second
1/1 Test #1: SleepFor1Second \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/CXXModules/CMP0155-OLD-stderr.txt b/Tests/RunCMake/CXXModules/CMP0155-OLD-stderr.txt
new file mode 100644
index 0000000..fdff8e4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/CMP0155-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0155-OLD\.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0155 will be removed from a future version
+ of CMake\.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances\. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnInterface-stderr.txt
index 70d00ee..607d638 100644
--- a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnInterface-stderr.txt
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnInterface-stderr.txt
@@ -1,5 +1,4 @@
CMake Error at FileSetModulesInterfaceOnInterface\.cmake:[0-9]+ \(target_sources\):
- target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE"
- visibility
+ target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE" scope
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnStatic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnStatic-stderr.txt
index 9e1613c..606c679 100644
--- a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnStatic-stderr.txt
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceOnStatic-stderr.txt
@@ -1,5 +1,4 @@
CMake Error at FileSetModulesInterfaceOnStatic\.cmake:[0-9]+ \(target_sources\):
- target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE"
- visibility
+ target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE" scope
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivateOnInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPrivateOnInterface-stderr.txt
index f949df9..1d9edea 100644
--- a/Tests/RunCMake/CXXModules/FileSetModulesPrivateOnInterface-stderr.txt
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivateOnInterface-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error at FileSetModulesPrivateOnInterface\.cmake:[0-9]+ \(target_sources\):
target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
- "PRIVATE" visibility on INTERFACE libraries\.
+ "PRIVATE" scope on INTERFACE libraries\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublicOnInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPublicOnInterface-stderr.txt
index 7d732eb..925ea98 100644
--- a/Tests/RunCMake/CXXModules/FileSetModulesPublicOnInterface-stderr.txt
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPublicOnInterface-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error at FileSetModulesPublicOnInterface\.cmake:[0-9]+ \(target_sources\):
target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
- "PRIVATE" visibility on INTERFACE libraries\.
+ "PRIVATE" scope on INTERFACE libraries\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CXXModules/NoScanningFileSetProperty-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CXXModules/NoScanningFileSetProperty-result.txt
diff --git a/Tests/RunCMake/CXXModules/NoScanningFileSetProperty-stderr.txt b/Tests/RunCMake/CXXModules/NoScanningFileSetProperty-stderr.txt
new file mode 100644
index 0000000..c8f4eec
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoScanningFileSetProperty-stderr.txt
@@ -0,0 +1,17 @@
+(CMake Error in CMakeLists\.txt:
+ The target named "noscanning-fs-property" has C\+\+ sources that may use
+ modules, but the compiler does not provide a way to discover the import
+ graph dependencies\. See the cmake-cxxmodules\(7\) manual for details\. Use
+ the CMAKE_CXX_SCAN_FOR_MODULES variable to enable or disable scanning\.
+|CMake Error in CMakeLists\.txt:
+ The target named "noscanning-fs-property" has C\+\+ sources that may use
+ modules, but modules are not supported by this generator:
+
+ [^
+]+
+
+ Modules are supported only by Ninja, Ninja Multi-Config, and Visual Studio
+ generators for VS 17\.4 and newer\. See the cmake-cxxmodules\(7\) manual for
+ details\. Use the CMAKE_CXX_SCAN_FOR_MODULES variable to enable or disable
+ scanning\.
+)
diff --git a/Tests/RunCMake/CXXModules/NoScanningFileSetProperty.cmake b/Tests/RunCMake/CXXModules/NoScanningFileSetProperty.cmake
new file mode 100644
index 0000000..a2d6fb3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoScanningFileSetProperty.cmake
@@ -0,0 +1,16 @@
+enable_language(CXX)
+unset(CMAKE_CXX_SCANDEP_SOURCE)
+
+add_executable(noscanning-fs-property)
+target_sources(noscanning-fs-property PRIVATE
+ FILE_SET SOURCES FILES sources/module-use.cxx)
+set_target_properties(noscanning-fs-property
+ PROPERTIES
+ CXX_STANDARD 20
+ CXX_STANDARD_REQUIRED ON
+ CXX_SCAN_FOR_MODULES 0)
+set_source_files_properties(sources/module-use.cxx
+ PROPERTIES
+ CXX_SCAN_FOR_MODULES 0)
+set_property(FILE_SET SOURCES TARGET noscanning-fs-property
+ PROPERTY CXX_SCAN_FOR_MODULES 1)
diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
index 31c5e3e..2a3ca3c 100644
--- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
@@ -22,6 +22,7 @@
endif ()
run_cmake(NoScanningSourceFileProperty)
+ run_cmake(NoScanningFileSetProperty)
run_cmake(NoScanningTargetProperty)
run_cmake(NoScanningVariable)
run_cmake(CMP0155-OLD)
diff --git a/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake b/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake
index cd24839..7cc7dbc 100644
--- a/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake
@@ -164,6 +164,8 @@
run_cxx_module_test(file-sets-with-dot)
run_cxx_module_test(vs-without-flags)
run_cxx_module_test(library library-static -DBUILD_SHARED_LIBS=OFF)
+ run_cxx_module_test(library library-static-file-set-SOURCES -DBUILD_SHARED_LIBS=OFF
+ -DWITH_FILE_SET_SOURCES=ON)
run_cxx_module_test(unity-build)
run_cxx_module_test(object-library)
run_cxx_module_test(generated)
@@ -172,6 +174,9 @@
run_cxx_module_test(non-trivial-collation-order-randomized)
run_cxx_module_test(duplicate)
set(RunCMake_CXXModules_NO_TEST 1)
+ if ("collation" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(private-cxx-modules)
+ endif ()
run_cxx_module_test(imp-from-object)
run_cxx_module_test(circular)
run_cxx_module_test(try-compile)
@@ -185,8 +190,7 @@
# BMI generation
if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND
RunCMake_GENERATOR MATCHES "Ninja")
- # FIXME(#25539,#27600,#27597): Restore per-importer BMI and enable this test.
- # run_cxx_module_test(mixed-bmi-compatibility)
+ run_cxx_module_test(mixed-bmi-compatibility)
endif()
if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND
diff --git a/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file-rebuild-check.cmake b/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file-rebuild-check.cmake
index 94e833a..4568873 100644
--- a/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file-rebuild-check.cmake
+++ b/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file-rebuild-check.cmake
@@ -1,12 +1,27 @@
-if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
- set(dep_modules_json_path "CMakeFiles/depchain_modules_json_file.dir/Debug/CXX.dd")
- set(modules_json_path "CMakeFiles/depchain_with_modules_json_file.dir/Debug/CXXModules.json")
-else ()
- set(dep_modules_json_path "CMakeFiles/depchain_modules_json_file.dir/CXX.dd")
- set(modules_json_path "CMakeFiles/depchain_with_modules_json_file.dir/CXXModules.json")
+file(GLOB synth_dirs
+ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/depchain_with_modules_json_file@synth_*.dir")
+
+list(LENGTH synth_dirs synth_dirs_len)
+if (NOT synth_dirs_len EQUAL 1)
+ list(APPEND RunCMake_TEST_FAILED
+ "Expected exactly one synthetic target for consuming 'depchain_with_modules_json_file' but found ${synth_dirs_len}: ${synth_dirs}")
endif ()
-if ("${RunCMake_TEST_BINARY_DIR}/${modules_json_path}" IS_NEWER_THAN "${RunCMake_TEST_BINARY_DIR}/${dep_modules_json_path}")
+list(GET synth_dirs 0 synth_dir)
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(dep_modules_json_path "CMakeFiles/depchain_modules_json_file.dir/Debug/CXX.dd")
+ set(modules_json_path "${synth_dir}/Debug/CXXModules.json")
+else ()
+ set(dep_modules_json_path "CMakeFiles/depchain_modules_json_file.dir/CXX.dd")
+ set(modules_json_path "${synth_dir}/CXXModules.json")
+endif ()
+
+
+if ("${modules_json_path}" IS_NEWER_THAN "${RunCMake_TEST_BINARY_DIR}/${dep_modules_json_path}")
+ cmake_path(RELATIVE_PATH modules_json_path
+ BASE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
list(APPEND RunCMake_TEST_FAILED
"Object '${dep_modules_json_path}' should have recompiled if '${modules_json_path}' changed.")
endif ()
diff --git a/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file/pre-rebuild.cmake b/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file/pre-rebuild.cmake
index 9c3f2ff..2b2ce92 100644
--- a/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file/pre-rebuild.cmake
+++ b/Tests/RunCMake/CXXModulesCompile/depchain-mods-json-file/pre-rebuild.cmake
@@ -1,7 +1,17 @@
+file(GLOB synth_dirs
+ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/depchain_with_modules_json_file@synth_*.dir")
+
+list(LENGTH synth_dirs synth_dirs_len)
+if (NOT synth_dirs_len EQUAL 1)
+ return()
+endif()
+
+list(GET synth_dirs 0 synth_dir)
+
if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
- set(modules_json_path "CMakeFiles/depchain_with_modules_json_file.dir/Debug/CXXModules.json")
+ set(modules_json_path "${synth_dir}/Debug/CXXModules.json")
else ()
- set(modules_json_path "CMakeFiles/depchain_with_modules_json_file.dir/CXXModules.json")
+ set(modules_json_path "${synth_dir}/CXXModules.json")
endif ()
-file(TOUCH_NOCREATE "${RunCMake_TEST_BINARY_DIR}/${modules_json_path}")
+file(TOUCH_NOCREATE "${modules_json_path}")
diff --git a/Tests/RunCMake/CXXModulesCompile/duplicate-sources-stderr.txt b/Tests/RunCMake/CXXModulesCompile/duplicate-sources-stderr.txt
deleted file mode 100644
index 1dfe3d3..0000000
--- a/Tests/RunCMake/CXXModulesCompile/duplicate-sources-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Warning \(dev\) in CMakeLists\.txt:
- Target "duplicate_sources" has source file
-
- [^
-]*/Tests/RunCMake/CXXModulesCompile/duplicate-sources/duplicate\.cxx
-
- in a "FILE_SET TYPE CXX_MODULES" multiple times\.
-This warning is for project developers\. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/CXXModulesCompile/library/CMakeLists.txt b/Tests/RunCMake/CXXModulesCompile/library/CMakeLists.txt
index d611029..ce05a4a 100644
--- a/Tests/RunCMake/CXXModulesCompile/library/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModulesCompile/library/CMakeLists.txt
@@ -23,6 +23,13 @@
importable.cxx)
target_compile_features(library PUBLIC cxx_std_20)
+if(WITH_FILE_SET_SOURCES)
+ target_sources(library
+ PUBLIC
+ FILE_SET SOURCES
+ FILES src.cpp)
+endif()
+
add_executable(exe)
target_link_libraries(exe PRIVATE library)
target_sources(exe
diff --git a/Tests/RunCMake/CXXModulesCompile/library/src.cpp b/Tests/RunCMake/CXXModulesCompile/library/src.cpp
new file mode 100644
index 0000000..16f5d59
--- /dev/null
+++ b/Tests/RunCMake/CXXModulesCompile/library/src.cpp
@@ -0,0 +1,3 @@
+void src()
+{
+}
diff --git a/Tests/RunCMake/CXXModulesCompile/ninja-cmp0154/CMakeLists.txt b/Tests/RunCMake/CXXModulesCompile/ninja-cmp0154/CMakeLists.txt
index 1aa36c1..07dc327 100644
--- a/Tests/RunCMake/CXXModulesCompile/ninja-cmp0154/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModulesCompile/ninja-cmp0154/CMakeLists.txt
@@ -27,5 +27,7 @@
set_property(SOURCE unrelated.cxx
PROPERTY
CXX_SCAN_FOR_MODULES 0)
+# ensure property INDEPENDENT_FILES=OFF is ignored
+set_property(FILE_SET CXX_MODULES TARGET ninja_cmp0154 PROPERTY INDEPENDENT_FILES OFF)
add_test(NAME ninja_cmp0154 COMMAND ninja_cmp0154)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules-build-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CXXModulesCompile/private-cxx-modules-build-result.txt
diff --git a/Tests/RunCMake/CXXModulesCompile/private-cxx-modules-build-stdout.txt b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules-build-stdout.txt
new file mode 100644
index 0000000..14cd00f
--- /dev/null
+++ b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules-build-stdout.txt
@@ -0,0 +1 @@
+CMake Error: Unable to use module 'importable' as it is 'PRIVATE' and therefore not accessible outside of its owning target\.
diff --git a/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/CMakeLists.txt b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/CMakeLists.txt
new file mode 100644
index 0000000..9a4bab4
--- /dev/null
+++ b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.24...3.28)
+project(cxx_modules_library CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(library)
+generate_export_header(library)
+target_sources(library
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/library_export.h"
+ PRIVATE
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.ixx
+ PRIVATE
+ importable.cxx)
+target_compile_features(library PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE library)
+target_sources(exe
+ PRIVATE
+ main.cxx)
diff --git a/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/importable.cxx b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/importable.cxx
new file mode 100644
index 0000000..859fa3d
--- /dev/null
+++ b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/importable.cxx
@@ -0,0 +1,6 @@
+module importable;
+
+int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/importable.ixx b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/importable.ixx
new file mode 100644
index 0000000..d3fb7f6
--- /dev/null
+++ b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/importable.ixx
@@ -0,0 +1,5 @@
+export module importable;
+
+#include "library_export.h"
+
+export LIBRARY_EXPORT int from_import();
diff --git a/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/main.cxx b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/main.cxx
new file mode 100644
index 0000000..feb38d2
--- /dev/null
+++ b/Tests/RunCMake/CXXModulesCompile/private-cxx-modules/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CommandLine/E_cat-stdin.cmake b/Tests/RunCMake/CommandLine/E_cat-stdin.cmake
index e83e619..e168bb9 100644
--- a/Tests/RunCMake/CommandLine/E_cat-stdin.cmake
+++ b/Tests/RunCMake/CommandLine/E_cat-stdin.cmake
@@ -1,10 +1,14 @@
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ell.txt" "ell")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ll.txt" "ll")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/rld.txt" "rld")
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo_append "H"
- COMMAND ${CMAKE_COMMAND} -E cat -
+ COMMAND ${CMAKE_COMMAND} -E cat - # Read stdin from - arg
+ )
+execute_process(
+ COMMAND ${CMAKE_COMMAND} -E echo_append "e"
+ COMMAND ${CMAKE_COMMAND} -E cat # Read stdin when no args
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo_append "o wo"
- COMMAND ${CMAKE_COMMAND} -E cat "${CMAKE_CURRENT_BINARY_DIR}/ell.txt" - "${CMAKE_CURRENT_BINARY_DIR}/rld.txt"
+ COMMAND ${CMAKE_COMMAND} -E cat "${CMAKE_CURRENT_BINARY_DIR}/ll.txt" - "${CMAKE_CURRENT_BINARY_DIR}/rld.txt"
)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/E_copy_directory-t-argument-no-source-dirs-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/E_copy_directory-t-argument-no-source-dirs-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_copy_directory-t-argument-no-source-dirs-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_directory-t-argument-no-source-dirs-stderr.txt
new file mode 100644
index 0000000..c3c3d6a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_directory-t-argument-no-source-dirs-stderr.txt
@@ -0,0 +1 @@
+^Error: No source directories specified \(for copy_directory command\)\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/E_copy_directory_if_different-t-argument-no-source-dirs-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/E_copy_directory_if_different-t-argument-no-source-dirs-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_copy_directory_if_different-t-argument-no-source-dirs-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_directory_if_different-t-argument-no-source-dirs-stderr.txt
new file mode 100644
index 0000000..371acbf
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_directory_if_different-t-argument-no-source-dirs-stderr.txt
@@ -0,0 +1 @@
+^Error: No source directories specified \(for copy_directory_if_different command\)\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/E_copy_directory_if_newer-t-argument-no-source-dirs-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/E_copy_directory_if_newer-t-argument-no-source-dirs-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_copy_directory_if_newer-t-argument-no-source-dirs-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_directory_if_newer-t-argument-no-source-dirs-stderr.txt
new file mode 100644
index 0000000..9af85a8
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_directory_if_newer-t-argument-no-source-dirs-stderr.txt
@@ -0,0 +1 @@
+^Error: No source directories specified \(for copy_directory_if_newer command\)\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-t-argument-target-is-file-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/E_copy_if_different-t-argument-target-is-file-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-t-argument-target-is-file-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-t-argument-target-is-file-stderr.txt
new file mode 100644
index 0000000..138ce81
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_if_different-t-argument-target-is-file-stderr.txt
@@ -0,0 +1 @@
+^Error: Target \(for copy_if_different command\).* is not a directory\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/E_copy_if_newer-t-argument-target-is-file-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/E_copy_if_newer-t-argument-target-is-file-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_newer-t-argument-target-is-file-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_if_newer-t-argument-target-is-file-stderr.txt
new file mode 100644
index 0000000..08eab4c
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_if_newer-t-argument-target-is-file-stderr.txt
@@ -0,0 +1 @@
+^Error: Target \(for copy_if_newer command\).* is not a directory\.$
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 584f38b..5dfdf9e 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -153,6 +153,15 @@
run_cmake_command(install-options-to-vars
${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars
--strip --prefix /var/test --config sample --component pack)
+run_cmake_command(install-no-component-value
+ ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars
+ --component)
+run_cmake_command(install-multi-component-1
+ ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars
+ --component comp1 comp2)
+run_cmake_command(install-multi-component-2
+ ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars
+ --component comp1 --component comp2)
run_cmake_command(install-default-dir-permissions-all
${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-permissions-install-options-to-vars
--default-directory-permissions u=rwx,g=rx,o=rx)
@@ -659,6 +668,12 @@
${CMAKE_COMMAND} -E copy ${in}/f1.txt -t ${out}/f1.txt ${in}/f3.txt)
run_cmake_command(E_copy-t-argument-no-source-files
${CMAKE_COMMAND} -E copy -t ${out})
+run_cmake_command(E_copy_if_different-t-argument
+ ${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt -t ${out} ${in}/f3.txt)
+run_cmake_command(E_copy_if_different-t-argument-target-is-file
+ ${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt -t ${out}/f1.txt ${in}/f3.txt)
+run_cmake_command(E_copy_if_different-t-argument-no-source-files
+ ${CMAKE_COMMAND} -E copy_if_different -t ${out})
run_cmake_command(E_copy_if_different-one-source-directory-target-is-directory
${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt ${out})
run_cmake_command(E_copy_if_different-three-source-files-target-is-directory
@@ -667,6 +682,12 @@
${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt ${in}/f2.txt ${in}/f3.txt ${out}/f1.txt)
run_cmake_command(E_copy_if_different-nonexistent-source
${CMAKE_COMMAND} -E copy_if_different ${in}/nonexistent.txt ${out})
+run_cmake_command(E_copy_if_newer-t-argument
+ ${CMAKE_COMMAND} -E copy_if_newer ${in}/f1.txt -t ${out} ${in}/f3.txt)
+run_cmake_command(E_copy_if_newer-t-argument-target-is-file
+ ${CMAKE_COMMAND} -E copy_if_newer ${in}/f1.txt -t ${out}/f1.txt ${in}/f3.txt)
+run_cmake_command(E_copy_if_newer-t-argument-no-source-files
+ ${CMAKE_COMMAND} -E copy_if_newer -t ${out})
run_cmake_command(E_copy_if_newer-one-source-directory-target-is-directory
${CMAKE_COMMAND} -E copy_if_newer ${in}/f1.txt ${out})
run_cmake_command(E_copy_if_newer-three-source-files-target-is-directory
@@ -684,8 +705,16 @@
file(MAKE_DIRECTORY ${out})
run_cmake_command(E_copy_directory_if_different
${CMAKE_COMMAND} -E copy_directory_if_different ${in} ${out})
+run_cmake_command(E_copy_directory_if_different-t-argument
+ ${CMAKE_COMMAND} -E copy_directory_if_different -t ${out} ${in})
+run_cmake_command(E_copy_directory_if_different-t-argument-no-source-dirs
+ ${CMAKE_COMMAND} -E copy_directory_if_different -t ${out})
run_cmake_command(E_copy_directory_if_newer
${CMAKE_COMMAND} -E copy_directory_if_newer ${in} ${out})
+run_cmake_command(E_copy_directory_if_newer-t-argument
+ ${CMAKE_COMMAND} -E copy_directory_if_newer -t ${out} ${in})
+run_cmake_command(E_copy_directory_if_newer-t-argument-no-source-dirs
+ ${CMAKE_COMMAND} -E copy_directory_if_newer -t ${out})
run_cmake_command(E_copy_directory_if_newer-nonexistent-source
${CMAKE_COMMAND} -E copy_directory_if_newer ${in}/nonexistent ${out}/target)
unset(in)
@@ -703,6 +732,10 @@
${CMAKE_COMMAND} -E copy_directory ${in}/d1 ${in}/d2 ${in}/d3 ${outfile})
run_cmake_command(E_copy_directory-three-source-files-target-is-not-exist
${CMAKE_COMMAND} -E copy_directory ${in}/d1 ${in}/d2 ${in}/d3 ${out}/not_existing_directory)
+run_cmake_command(E_copy_directory-t-argument
+ ${CMAKE_COMMAND} -E copy_directory -t ${out} ${in}/d1 ${in}/d2 ${in}/d3)
+run_cmake_command(E_copy_directory-t-argument-no-source-dirs
+ ${CMAKE_COMMAND} -E copy_directory -t ${out})
unset(in)
unset(out)
unset(outfile)
@@ -1013,37 +1046,39 @@
"-DFOO:STRING=-DBAR:BOOL=BAZ")
run_cmake(D_typed_nested_cache)
-set(RunCMake_TEST_OPTIONS -Wno-dev)
-run_cmake(Wno-dev)
-unset(RunCMake_TEST_OPTIONS)
-
+# -Wdev is a deprecated synonym for -Wauthor
set(RunCMake_TEST_OPTIONS -Wdev)
run_cmake(Wdev)
unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS -Werror=dev)
-run_cmake(Werror_dev)
+set(RunCMake_TEST_OPTIONS -Wno-author)
+run_cmake(Wno-author)
unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS -Wno-error=dev)
-run_cmake(Wno-error_deprecated)
+set(RunCMake_TEST_OPTIONS -Wauthor)
+run_cmake(Wauthor)
unset(RunCMake_TEST_OPTIONS)
-# -Wdev should not override deprecated options if specified
-set(RunCMake_TEST_OPTIONS -Wdev -Wno-deprecated)
-run_cmake(Wno-deprecated)
+set(RunCMake_TEST_OPTIONS -Werror=author)
+run_cmake(Werror_author)
unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS -Wno-deprecated -Wdev)
+
+set(RunCMake_TEST_OPTIONS -Wno-error=author)
+run_cmake(Wno-error_author)
+unset(RunCMake_TEST_OPTIONS)
+
+# -Wauthor should not override deprecated options if specified
+set(RunCMake_TEST_OPTIONS -Wauthor -Wno-deprecated)
run_cmake(Wno-deprecated)
unset(RunCMake_TEST_OPTIONS)
-# -Wdev should enable deprecated warnings as well
-set(RunCMake_TEST_OPTIONS -Wdev)
+# -Wauthor should enable deprecated warnings as well
+set(RunCMake_TEST_OPTIONS -Wauthor)
run_cmake(Wdeprecated)
unset(RunCMake_TEST_OPTIONS)
-# -Werror=dev should enable deprecated errors as well
-set(RunCMake_TEST_OPTIONS -Werror=dev)
+# -Werror=author should enable deprecated errors as well
+set(RunCMake_TEST_OPTIONS -Werror=author)
run_cmake(Werror_deprecated)
unset(RunCMake_TEST_OPTIONS)
@@ -1067,23 +1102,28 @@
run_cmake(Wno-error_deprecated)
unset(RunCMake_TEST_OPTIONS)
-# Dev warnings should be on by default
-run_cmake(Wdev)
+# Author warnings should be on by default
+run_cmake(Wauthor)
# Deprecated warnings should be on by default
run_cmake(Wdeprecated)
# Conflicting -W options should honor the last value
-set(RunCMake_TEST_OPTIONS -Wno-dev -Wdev)
-run_cmake(Wdev)
+set(RunCMake_TEST_OPTIONS -Wno-author -Wauthor)
+run_cmake(Wauthor)
unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS -Wdev -Wno-dev)
-run_cmake(Wno-dev)
+set(RunCMake_TEST_OPTIONS -Wauthor -Wno-author)
+run_cmake(Wno-author)
+unset(RunCMake_TEST_OPTIONS)
+
+set(RunCMake_TEST_OPTIONS -Wno-deprecated -Wuninitialized)
+run_cmake(Wuninitialized)
unset(RunCMake_TEST_OPTIONS)
run_cmake_command(W_bad-arg1 ${CMAKE_COMMAND} -B DummyBuildDir -W)
run_cmake_command(W_bad-arg2 ${CMAKE_COMMAND} -B DummyBuildDir -Wno-)
run_cmake_command(W_bad-arg3 ${CMAKE_COMMAND} -B DummyBuildDir -Werror=)
+run_cmake_command(W_bad-arg4 ${CMAKE_COMMAND} -B DummyBuildDir -Wimaginary)
set(RunCMake_TEST_OPTIONS --debug-output)
run_cmake(debug-output)
@@ -1098,7 +1138,7 @@
run_cmake(trace-expand)
unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS --trace-expand --warn-uninitialized)
+set(RunCMake_TEST_OPTIONS --trace-expand -Wuninitialized)
run_cmake(trace-expand-warn-uninitialized)
unset(RunCMake_TEST_OPTIONS)
@@ -1119,10 +1159,6 @@
run_cmake(trace-json-v1-expand)
unset(RunCMake_TEST_OPTIONS)
-set(RunCMake_TEST_OPTIONS -Wno-deprecated --warn-uninitialized)
-run_cmake(warn-uninitialized)
-unset(RunCMake_TEST_OPTIONS)
-
set(RunCMake_TEST_OPTIONS --trace-source=trace-only-this-file.cmake)
run_cmake(trace-source)
unset(RunCMake_TEST_OPTIONS)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/W_bad-arg4-result.txt
similarity index 100%
rename from Tests/RunCMake/CommandLine/Werror_dev-result.txt
rename to Tests/RunCMake/CommandLine/W_bad-arg4-result.txt
diff --git a/Tests/RunCMake/CommandLine/W_bad-arg4-stderr.txt b/Tests/RunCMake/CommandLine/W_bad-arg4-stderr.txt
new file mode 100644
index 0000000..e79fc0d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/W_bad-arg4-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: The warning category "imaginary" is not known.
+CMake Error: Run 'cmake --help' for all supported options\.
diff --git a/Tests/RunCMake/CommandLine/Wauthor-stderr.txt b/Tests/RunCMake/CommandLine/Wauthor-stderr.txt
new file mode 100644
index 0000000..5d4f46d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Wauthor-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning \(dev\) at Wauthor\.cmake:1 \(message\):
+ Some author warning
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at Wauthor\.cmake:6 \(include\):
+ include\(\) given empty file name \(ignored\)\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLine/Wauthor.cmake b/Tests/RunCMake/CommandLine/Wauthor.cmake
new file mode 100644
index 0000000..29beff1
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Wauthor.cmake
@@ -0,0 +1,6 @@
+message(AUTHOR_WARNING "Some author warning")
+
+# with -Wauthor this will also cause an AUTHOR_WARNING message, checks that
+# messages issued outside of the message command, by other CMake commands, also
+# are affected by -Wauthor
+include("")
diff --git a/Tests/RunCMake/CommandLine/Wdev-stderr.txt b/Tests/RunCMake/CommandLine/Wdev-stderr.txt
index 31ed21b..ec70004 100644
--- a/Tests/RunCMake/CommandLine/Wdev-stderr.txt
+++ b/Tests/RunCMake/CommandLine/Wdev-stderr.txt
@@ -1,4 +1,5 @@
-^CMake Warning \(dev\) at Wdev\.cmake:1 \(message\):
+^The dev option is deprecated\. Use -Wauthor instead\.
+CMake Warning \(dev\) at Wdev\.cmake:1 \(message\):
Some author warning
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/Werror_author-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/Werror_author-result.txt
diff --git a/Tests/RunCMake/CommandLine/Werror_author-stderr.txt b/Tests/RunCMake/CommandLine/Werror_author-stderr.txt
new file mode 100644
index 0000000..f6fdcd6
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Werror_author-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Error \(dev\) at Werror_author\.cmake:4 \(include\):
+ include\(\) given empty file name \(ignored\)\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This error is for project developers\. Use -Wno-error=dev to suppress it\.
+
+CMake Error \(dev\) at Werror_author\.cmake:7 \(message\):
+ Some author warning
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This error is for project developers\. Use -Wno-error=dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_author.cmake b/Tests/RunCMake/CommandLine/Werror_author.cmake
new file mode 100644
index 0000000..4b83606
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Werror_author.cmake
@@ -0,0 +1,7 @@
+# with -Werror=author this will also cause an (upgraded) AUTHOR_ERROR message,
+# checks that messages issued outside of the message command, by other CMake
+# commands, also are affected by -Werror=author
+include("")
+
+# message command sets fatal occurred flag, so run it last
+message(AUTHOR_WARNING "Some author warning")
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-stderr.txt b/Tests/RunCMake/CommandLine/Werror_dev-stderr.txt
deleted file mode 100644
index 7a36b00..0000000
--- a/Tests/RunCMake/CommandLine/Werror_dev-stderr.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-^CMake Error \(dev\) at Werror_dev\.cmake:4 \(include\):
- include\(\) given empty file name \(ignored\)\.
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
-This error is for project developers\. Use -Wno-error=dev to suppress it\.
-
-CMake Error \(dev\) at Werror_dev\.cmake:7 \(message\):
- Some author warning
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
-This error is for project developers\. Use -Wno-error=dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLine/Werror_dev.cmake b/Tests/RunCMake/CommandLine/Werror_dev.cmake
deleted file mode 100644
index 05f333a..0000000
--- a/Tests/RunCMake/CommandLine/Werror_dev.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# with -Werror=dev this will also cause an (upgraded) AUTHOR_ERROR message,
-# checks that messages issued outside of the message command, by other CMake
-# commands, also are affected by -Werror=dev
-include("")
-
-# message command sets fatal occurred flag, so run it last
-message(AUTHOR_WARNING "Some author warning")
diff --git a/Tests/RunCMake/CommandLine/Wno-author.cmake b/Tests/RunCMake/CommandLine/Wno-author.cmake
new file mode 100644
index 0000000..67a7bde
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Wno-author.cmake
@@ -0,0 +1,6 @@
+message(AUTHOR_WARNING "Some author warning")
+
+# without -Wno-author this will also cause an AUTHOR_WARNING message, checks
+# that messages issued outside of the message command, by other CMake commands,
+# also are affected by -Wno-author
+include("")
diff --git a/Tests/RunCMake/CommandLine/Wno-dev.cmake b/Tests/RunCMake/CommandLine/Wno-dev.cmake
deleted file mode 100644
index 802b435..0000000
--- a/Tests/RunCMake/CommandLine/Wno-dev.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-message(AUTHOR_WARNING "Some author warning")
-
-# without -Wno-dev this will also cause an AUTHOR_WARNING message, checks that
-# messages issued outside of the message command, by other CMake commands, also
-# are affected by -Wno-dev
-include("")
diff --git a/Tests/RunCMake/CommandLine/Wno-error_author-stderr.txt b/Tests/RunCMake/CommandLine/Wno-error_author-stderr.txt
new file mode 100644
index 0000000..e466e22
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Wno-error_author-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning \(dev\) at Wno-error_author\.cmake:2 \(message\):
+ Some author warning
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at Wno-error_author\.cmake:7 \(include\):
+ include\(\) given empty file name \(ignored\)\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLine/Wno-error_author.cmake b/Tests/RunCMake/CommandLine/Wno-error_author.cmake
new file mode 100644
index 0000000..7e10fcb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Wno-error_author.cmake
@@ -0,0 +1,7 @@
+# This should still produce a warning when -Wno-error=author is specified
+message(AUTHOR_WARNING "Some author warning")
+
+# with -Wno-error=author this will also cause an AUTHOR_WARNING message, checks
+# that messages issued outside of the message command, by other CMake commands,
+# also are affected by -Wno-error=author
+include("")
diff --git a/Tests/RunCMake/CommandLine/Wno-error_dev-stderr.txt b/Tests/RunCMake/CommandLine/Wno-error_dev-stderr.txt
deleted file mode 100644
index 1beaaad..0000000
--- a/Tests/RunCMake/CommandLine/Wno-error_dev-stderr.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-^CMake Warning \(dev\) at Wno-error_dev\.cmake:2 \(message\):
- Some author warning
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
-This warning is for project developers\. Use -Wno-dev to suppress it\.
-
-CMake Warning \(dev\) at Wno-error_dev\.cmake:6 \(include\):
- include\(\) given empty file name \(ignored\)\.
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
-This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLine/Wno-error_dev.cmake b/Tests/RunCMake/CommandLine/Wno-error_dev.cmake
deleted file mode 100644
index b700c19..0000000
--- a/Tests/RunCMake/CommandLine/Wno-error_dev.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# This should still produce a warning when -Wno-error=dev is specified
-message(AUTHOR_WARNING "Some author warning")
-
-# with -Wno-error=dev this will also cause an AUTHOR_WARNING message, checks
-# that messages issued outside of the message command, by other CMake commands,
-# also are affected by -Wno-error=dev
-include("")
diff --git a/Tests/RunCMake/CommandLine/Wuninitialized-stderr.txt b/Tests/RunCMake/CommandLine/Wuninitialized-stderr.txt
new file mode 100644
index 0000000..2b8eaf8
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Wuninitialized-stderr.txt
@@ -0,0 +1,23 @@
+CMake Warning \(dev\) at Wuninitialized\.cmake:1 \(set\):
+ uninitialized variable 'NEW_WARN_FROM_NORMAL_CMAKE_FILE_INSIDE_BRACES'
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at Wuninitialized\.cmake:2 \(string\):
+ uninitialized variable 'NEW_WARN_FROM_STRING_CONFIGURE_INSIDE_BRACES'
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at Wuninitialized\.cmake:4 \(configure_file\):
+ uninitialized variable 'NEW_WARN_FROM_CONFIGURE_FILE_INSIDE_AT'
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at Wuninitialized\.cmake:5 \(string\):
+ uninitialized variable 'NEW_WARN_FROM_STRING_CONFIGURE_INSIDE_AT'
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLine/warn-uninitialized.cmake b/Tests/RunCMake/CommandLine/Wuninitialized.cmake
similarity index 100%
rename from Tests/RunCMake/CommandLine/warn-uninitialized.cmake
rename to Tests/RunCMake/CommandLine/Wuninitialized.cmake
diff --git a/Tests/RunCMake/CommandLine/install-multi-component-1-stderr.txt b/Tests/RunCMake/CommandLine/install-multi-component-1-stderr.txt
new file mode 100644
index 0000000..4abd24e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-multi-component-1-stderr.txt
@@ -0,0 +1,2 @@
+CMAKE_INSTALL_COMPONENT is comp1
+CMAKE_INSTALL_COMPONENT is comp2
diff --git a/Tests/RunCMake/CommandLine/install-multi-component-2-stderr.txt b/Tests/RunCMake/CommandLine/install-multi-component-2-stderr.txt
new file mode 100644
index 0000000..4abd24e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-multi-component-2-stderr.txt
@@ -0,0 +1,2 @@
+CMAKE_INSTALL_COMPONENT is comp1
+CMAKE_INSTALL_COMPONENT is comp2
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLine/install-no-component-value-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLine/install-no-component-value-result.txt
diff --git a/Tests/RunCMake/CommandLine/install-no-component-value-stderr.txt b/Tests/RunCMake/CommandLine/install-no-component-value-stderr.txt
new file mode 100644
index 0000000..a8eff7c
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-no-component-value-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Invalid value used with --component
diff --git a/Tests/RunCMake/CommandLine/warn-uninitialized-stderr.txt b/Tests/RunCMake/CommandLine/warn-uninitialized-stderr.txt
deleted file mode 100644
index 31ff067..0000000
--- a/Tests/RunCMake/CommandLine/warn-uninitialized-stderr.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-CMake Warning \(dev\) at warn-uninitialized\.cmake:1 \(set\):
- uninitialized variable 'NEW_WARN_FROM_NORMAL_CMAKE_FILE_INSIDE_BRACES'
-Call Stack \(most recent call first\):
- CMakeLists\.txt:3 \(include\)
-This warning is for project developers\. Use -Wno-dev to suppress it\.
-
-CMake Warning \(dev\) at warn-uninitialized\.cmake:2 \(string\):
- uninitialized variable 'NEW_WARN_FROM_STRING_CONFIGURE_INSIDE_BRACES'
-Call Stack \(most recent call first\):
- CMakeLists\.txt:3 \(include\)
-This warning is for project developers\. Use -Wno-dev to suppress it\.
-
-CMake Warning \(dev\) at warn-uninitialized\.cmake:4 \(configure_file\):
- uninitialized variable 'NEW_WARN_FROM_CONFIGURE_FILE_INSIDE_AT'
-Call Stack \(most recent call first\):
- CMakeLists\.txt:3 \(include\)
-This warning is for project developers\. Use -Wno-dev to suppress it\.
-
-CMake Warning \(dev\) at warn-uninitialized\.cmake:5 \(string\):
- uninitialized variable 'NEW_WARN_FROM_STRING_CONFIGURE_INSIDE_AT'
-Call Stack \(most recent call first\):
- CMakeLists\.txt:3 \(include\)
-This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
index e2b0ca7..01c2f7e 100644
--- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
@@ -119,6 +119,34 @@
run_cmake(compression-method-zstd)
run_cmake(compression-method-ppmd)
+# Encoding tests. These rely on UTF-8 encoding of our test sources.
+if(NOT DEFINED CMake_TEST_LOCALE_CHARSET)
+ cmake_host_system_information(RESULT CMake_TEST_LOCALE_CHARSET QUERY LOCALE_CHARSET)
+ message(STATUS "Detected LOCALE_CHARSET '${CMake_TEST_LOCALE_CHARSET}'")
+endif()
+if(CMake_TEST_LOCALE_CHARSET STREQUAL "UTF-8")
+ if(CMAKE_HOST_WIN32)
+ # The OEM encoding cannot represent our UTF-8 test paths.
+ run_cmake(encoding-oem-gnutar-fails)
+ run_cmake(encoding-oem-zip-fails)
+ else()
+ run_cmake(encoding-oem-gnutar)
+ run_cmake(encoding-oem-zip)
+ endif()
+
+ run_cmake(encoding-oem-7zip)
+ run_cmake(encoding-oem-pax)
+ run_cmake(encoding-oem-paxr)
+
+ run_cmake(encoding-utf-8-7zip)
+ run_cmake(encoding-utf-8-gnutar)
+ run_cmake(encoding-utf-8-pax)
+ run_cmake(encoding-utf-8-paxr)
+ run_cmake(encoding-utf-8-zip)
+else()
+ message(STATUS "encoding-* - SKIPPED due to non-UTF-8 locale")
+endif()
+
# Extracting only selected files or directories
run_cmake(zip-filtered)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-7zip.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-7zip.cmake
new file mode 100644
index 0000000..722ca8e
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-7zip.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.7z")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=7zip --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("377abcaf271c" LIMIT 6 HEX)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails-result.txt
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails-stderr.txt b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails-stderr.txt
new file mode 100644
index 0000000..ba1bc13
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^
+]*
+CMake Error: Problem creating tar:
+[^
+]*/bad\.tar
+CMake Error at roundtrip\.cmake:[0-9]+ \(message\):
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails.cmake
new file mode 100644
index 0000000..10ae837
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar-fails.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "bad.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=gnutar --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar.cmake
new file mode 100644
index 0000000..93bcd1c
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-gnutar.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=gnutar --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-pax.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-pax.cmake
new file mode 100644
index 0000000..603ef66
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-pax.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=pax --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-paxr.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-paxr.cmake
new file mode 100644
index 0000000..12b6197
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-paxr.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=paxr --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails-result.txt
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails-stderr.txt b/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails-stderr.txt
new file mode 100644
index 0000000..5f0acc3
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^
+]*
+CMake Error: Problem creating tar:
+[^
+]*/bad\.zip
+CMake Error at roundtrip\.cmake:[0-9]+ \(message\):
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails.cmake
new file mode 100644
index 0000000..17e3da3
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-zip-fails.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "bad.zip")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=zip --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-oem-zip.cmake b/Tests/RunCMake/CommandLineTar/encoding-oem-zip.cmake
new file mode 100644
index 0000000..5112770
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-oem-zip.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.zip")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=zip --cmake-tar-encoding=OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=OEM)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-utf-8-7zip.cmake b/Tests/RunCMake/CommandLineTar/encoding-utf-8-7zip.cmake
new file mode 100644
index 0000000..cdecb90
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-utf-8-7zip.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.7z")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=7zip --cmake-tar-encoding=UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=UTF-8)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("377abcaf271c" LIMIT 6 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-utf-8-gnutar.cmake b/Tests/RunCMake/CommandLineTar/encoding-utf-8-gnutar.cmake
new file mode 100644
index 0000000..e74f87f
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-utf-8-gnutar.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=gnutar --cmake-tar-encoding=UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=UTF-8)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-utf-8-pax.cmake b/Tests/RunCMake/CommandLineTar/encoding-utf-8-pax.cmake
new file mode 100644
index 0000000..10b2342
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-utf-8-pax.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=pax --cmake-tar-encoding=UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=UTF-8)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-utf-8-paxr.cmake b/Tests/RunCMake/CommandLineTar/encoding-utf-8-paxr.cmake
new file mode 100644
index 0000000..5adc9dc
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-utf-8-paxr.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.tar")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=paxr --cmake-tar-encoding=UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=UTF-8)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/encoding-utf-8-zip.cmake b/Tests/RunCMake/CommandLineTar/encoding-utf-8-zip.cmake
new file mode 100644
index 0000000..fded11f
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/encoding-utf-8-zip.cmake
@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.zip")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=zip --cmake-tar-encoding=UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(DECOMPRESSION_OPTIONS --cmake-tar-encoding=UTF-8)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/CommandLineTar/roundtrip.cmake b/Tests/RunCMake/CommandLineTar/roundtrip.cmake
index eeafcdb..af7601f 100644
--- a/Tests/RunCMake/CommandLineTar/roundtrip.cmake
+++ b/Tests/RunCMake/CommandLineTar/roundtrip.cmake
@@ -11,7 +11,7 @@
)
if(NOT result STREQUAL "0")
- message(FATAL_ERROR "tar failed with arguments [${ARGN}] result [${result}]")
+ message(FATAL_ERROR "tar failed with arguments:\n ${ARGN}\nresult:\n ${result}")
endif()
endfunction()
@@ -31,6 +31,7 @@
"d_4/f1.txt"
"d-4/f1.txt"
"My Special Directory/f1.txt"
+ ${COMPRESSION_ADDITIONAL_FILE_NAMES}
)
foreach(file ${CHECK_FILES})
@@ -64,18 +65,25 @@
set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file})
if(NOT EXISTS ${input})
- message(SEND_ERROR "Cannot find input file ${output}")
+ message(SEND_ERROR "Cannot find input file:\n \"${output}\"")
endif()
if(NOT EXISTS ${output})
- message(SEND_ERROR "Cannot find output file ${output}")
+ message(SEND_ERROR "Cannot find output file:\n \"${output}\"")
endif()
file(MD5 ${input} input_md5)
file(MD5 ${output} output_md5)
if(NOT input_md5 STREQUAL output_md5)
- message(SEND_ERROR "Files \"${input}\" and \"${output}\" are different")
+ message(SEND_ERROR
+ "Files:\n"
+ " \"${input}\"\n"
+ "and\n"
+ " \"${output}\"\n"
+ "are different"
+ )
+
endif()
endforeach()
@@ -83,7 +91,7 @@
set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file})
if(EXISTS ${output})
- message(SEND_ERROR "File ${output} exists but it shouldn't")
+ message(SEND_ERROR "File exists but it shouldn't:\n \"${output}\"")
endif()
endforeach()
diff --git a/Tests/RunCMake/CommandLineTar/utf-8-paths.cmake b/Tests/RunCMake/CommandLineTar/utf-8-paths.cmake
new file mode 100644
index 0000000..af85ffa
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/utf-8-paths.cmake
@@ -0,0 +1,10 @@
+list(APPEND COMPRESSION_ADDITIONAL_FILE_NAMES
+ "arabic-نَسِيج.txt"
+ "armenian-Բարեւ ձեզ.txt"
+ "chinese-质地.txt"
+ "cyrillic-привет.txt"
+ "greek-Γεια.txt"
+ "hungarian-hűtő.txt"
+ "japanese-テクスチャ.txt"
+ "korean-조직.txt"
+)
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt b/Tests/RunCMake/CompileFeatures/NotEnabled-result.txt
similarity index 100%
rename from Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt
rename to Tests/RunCMake/CompileFeatures/NotEnabled-result.txt
diff --git a/Tests/RunCMake/CompileFeatures/NotEnabled-stderr.txt b/Tests/RunCMake/CompileFeatures/NotEnabled-stderr.txt
new file mode 100644
index 0000000..999778d
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotEnabled-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error at NotEnabled.cmake:[0-9]+ \(target_compile_definitions\):
+ Error evaluating generator expression:
+
+ \$<COMPILE_FEATURES:c_std_99>
+
+ cannot use features from non-enabled language C
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CompileFeatures/NotEnabled.cmake b/Tests/RunCMake/CompileFeatures/NotEnabled.cmake
new file mode 100644
index 0000000..6b8a362
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotEnabled.cmake
@@ -0,0 +1,2 @@
+add_library(empty empty.cpp)
+target_compile_definitions(empty PRIVATE FOO=$<COMPILE_FEATURES:c_std_99>)
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index 508662e..b990a51 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -7,6 +7,7 @@
run_cmake(NotAFeature_OriginDebugGenex)
run_cmake(NotAFeature_OriginDebugTransitive)
run_cmake(NotAFeature_OriginDebugCommand)
+run_cmake(NotEnabled)
run_cmake(compiler_introspection)
include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake")
diff --git a/Tests/RunCMake/DiagnosticScope/Block.cmake b/Tests/RunCMake/DiagnosticScope/Block.cmake
new file mode 100644
index 0000000..a69324d
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/Block.cmake
@@ -0,0 +1,22 @@
+cmake_diagnostic(SET CMD_AUTHOR IGNORE)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "IGNORE")
+ message(SEND_ERROR "failed to set diagnostic state")
+endif()
+
+block(SCOPE_FOR DIAGNOSTICS)
+
+cmake_diagnostic(SET CMD_AUTHOR SEND_ERROR)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "SEND_ERROR")
+ message(SEND_ERROR "failed to set diagnostic state")
+endif()
+
+endblock()
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "IGNORE")
+ message(SEND_ERROR "failed to restore diagnostic state")
+endif()
diff --git a/Tests/RunCMake/DiagnosticScope/CMakeLists.txt b/Tests/RunCMake/DiagnosticScope/CMakeLists.txt
new file mode 100644
index 0000000..d383479
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 4.3)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_DIAGNOSTIC_SCOPE)
diff --git a/Tests/RunCMake/DiagnosticScope/DiagnosticInclude.cmake b/Tests/RunCMake/DiagnosticScope/DiagnosticInclude.cmake
new file mode 100644
index 0000000..1d9d748
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/DiagnosticInclude.cmake
@@ -0,0 +1,6 @@
+cmake_diagnostic(SET CMD_AUTHOR SEND_ERROR)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "SEND_ERROR")
+ message(SEND_ERROR "failed to set diagnostic state")
+endif()
diff --git a/Tests/RunCMake/DiagnosticScope/IncludeWithScope.cmake b/Tests/RunCMake/DiagnosticScope/IncludeWithScope.cmake
new file mode 100644
index 0000000..2de0db5
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/IncludeWithScope.cmake
@@ -0,0 +1,7 @@
+cmake_diagnostic(SET CMD_AUTHOR WARN)
+include(DiagnosticInclude.cmake)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "WARN")
+ message(SEND_ERROR "include unexpectedly leaked diagnostic state")
+endif()
diff --git a/Tests/RunCMake/DiagnosticScope/IncludeWithoutScope.cmake b/Tests/RunCMake/DiagnosticScope/IncludeWithoutScope.cmake
new file mode 100644
index 0000000..fa71e3f
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/IncludeWithoutScope.cmake
@@ -0,0 +1,7 @@
+cmake_diagnostic(SET CMD_AUTHOR WARN)
+include(DiagnosticInclude.cmake NO_DIAGNOSTIC_SCOPE)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "SEND_ERROR")
+ message(SEND_ERROR "include unexpectedly encapsulated diagnostic state")
+endif()
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/DiagnosticScope/NotClosed-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/DiagnosticScope/NotClosed-result.txt
diff --git a/Tests/RunCMake/DiagnosticScope/NotClosed-stderr.txt b/Tests/RunCMake/DiagnosticScope/NotClosed-stderr.txt
new file mode 100644
index 0000000..27dc157
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/NotClosed-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error in NotClosed\.cmake:
+ cmake_diagnostic PUSH without matching POP
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/DiagnosticScope/NotClosed.cmake b/Tests/RunCMake/DiagnosticScope/NotClosed.cmake
new file mode 100644
index 0000000..17d62bc
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/NotClosed.cmake
@@ -0,0 +1 @@
+cmake_diagnostic(PUSH)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/DiagnosticScope/NotOpened-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/DiagnosticScope/NotOpened-result.txt
diff --git a/Tests/RunCMake/DiagnosticScope/NotOpened-stderr.txt b/Tests/RunCMake/DiagnosticScope/NotOpened-stderr.txt
new file mode 100644
index 0000000..bdd1003
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/NotOpened-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NotOpened\.cmake:[0-9]+ \(cmake_diagnostic\):
+ cmake_diagnostic POP without matching PUSH
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/DiagnosticScope/NotOpened.cmake b/Tests/RunCMake/DiagnosticScope/NotOpened.cmake
new file mode 100644
index 0000000..be5e5f8
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/NotOpened.cmake
@@ -0,0 +1 @@
+cmake_diagnostic(POP)
diff --git a/Tests/RunCMake/DiagnosticScope/PushPop.cmake b/Tests/RunCMake/DiagnosticScope/PushPop.cmake
new file mode 100644
index 0000000..055506b
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/PushPop.cmake
@@ -0,0 +1,22 @@
+cmake_diagnostic(SET CMD_AUTHOR IGNORE)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "IGNORE")
+ message(SEND_ERROR "failed to set diagnostic state")
+endif()
+
+cmake_diagnostic(PUSH)
+
+cmake_diagnostic(SET CMD_AUTHOR SEND_ERROR)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "SEND_ERROR")
+ message(SEND_ERROR "failed to set diagnostic state")
+endif()
+
+cmake_diagnostic(POP)
+
+cmake_diagnostic(GET CMD_AUTHOR action)
+if(NOT "${action}" STREQUAL "IGNORE")
+ message(SEND_ERROR "failed to restore diagnostic state")
+endif()
diff --git a/Tests/RunCMake/DiagnosticScope/RunCMakeTest.cmake b/Tests/RunCMake/DiagnosticScope/RunCMakeTest.cmake
new file mode 100644
index 0000000..ed6a4a0
--- /dev/null
+++ b/Tests/RunCMake/DiagnosticScope/RunCMakeTest.cmake
@@ -0,0 +1,8 @@
+include(RunCMake)
+
+run_cmake(PushPop)
+run_cmake(Block)
+run_cmake(IncludeWithScope)
+run_cmake(IncludeWithoutScope)
+run_cmake(NotClosed)
+run_cmake(NotOpened)
diff --git a/Tests/RunCMake/Diagnostics/Actions.cmake b/Tests/RunCMake/Diagnostics/Actions.cmake
new file mode 100644
index 0000000..06a1e5a
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/Actions.cmake
@@ -0,0 +1,74 @@
+function(run_test ACTION INIT TARGET EXPECTED)
+ cmake_diagnostic(SET CMD_DEPRECATED ${INIT})
+
+ cmake_diagnostic(GET CMD_DEPRECATED action)
+ if(NOT "${action}" STREQUAL "${INIT}")
+ message(SEND_ERROR "failed to set diagnostic state")
+ endif()
+
+ cmake_diagnostic(${ACTION} CMD_AUTHOR ${TARGET} RECURSE)
+
+ cmake_diagnostic(GET CMD_DEPRECATED action)
+ if(NOT "${action}" STREQUAL "${EXPECTED}")
+ message(SEND_ERROR
+ "failed to change diagnostic state"
+ " (expected '${EXPECTED}', actual '${action}')"
+ )
+ endif()
+endfunction()
+
+# Run tests for altering a diagnostic from a known state
+run_test(SET IGNORE WARN WARN)
+run_test(SET IGNORE SEND_ERROR SEND_ERROR)
+run_test(SET IGNORE FATAL_ERROR FATAL_ERROR)
+
+run_test(PROMOTE IGNORE IGNORE IGNORE)
+run_test(PROMOTE IGNORE WARN WARN)
+run_test(PROMOTE IGNORE SEND_ERROR SEND_ERROR)
+run_test(PROMOTE IGNORE FATAL_ERROR FATAL_ERROR)
+
+run_test(PROMOTE WARN IGNORE WARN)
+run_test(PROMOTE WARN WARN WARN)
+run_test(PROMOTE WARN SEND_ERROR SEND_ERROR)
+run_test(PROMOTE WARN FATAL_ERROR FATAL_ERROR)
+
+run_test(PROMOTE SEND_ERROR IGNORE SEND_ERROR)
+run_test(PROMOTE SEND_ERROR WARN SEND_ERROR)
+run_test(PROMOTE SEND_ERROR SEND_ERROR SEND_ERROR)
+run_test(PROMOTE SEND_ERROR FATAL_ERROR FATAL_ERROR)
+
+run_test(PROMOTE FATAL_ERROR IGNORE FATAL_ERROR)
+run_test(PROMOTE FATAL_ERROR WARN FATAL_ERROR)
+run_test(PROMOTE FATAL_ERROR SEND_ERROR FATAL_ERROR)
+run_test(PROMOTE FATAL_ERROR FATAL_ERROR FATAL_ERROR)
+
+run_test(DEMOTE IGNORE IGNORE IGNORE)
+run_test(DEMOTE IGNORE WARN IGNORE)
+run_test(DEMOTE IGNORE SEND_ERROR IGNORE)
+run_test(DEMOTE IGNORE FATAL_ERROR IGNORE)
+
+run_test(DEMOTE WARN IGNORE IGNORE)
+run_test(DEMOTE WARN WARN WARN)
+run_test(DEMOTE WARN SEND_ERROR WARN)
+run_test(DEMOTE WARN FATAL_ERROR WARN)
+
+run_test(DEMOTE SEND_ERROR IGNORE IGNORE)
+run_test(DEMOTE SEND_ERROR WARN WARN)
+run_test(DEMOTE SEND_ERROR SEND_ERROR SEND_ERROR)
+run_test(DEMOTE SEND_ERROR FATAL_ERROR SEND_ERROR)
+
+run_test(DEMOTE FATAL_ERROR IGNORE IGNORE)
+run_test(DEMOTE FATAL_ERROR WARN WARN)
+run_test(DEMOTE FATAL_ERROR SEND_ERROR SEND_ERROR)
+run_test(DEMOTE FATAL_ERROR FATAL_ERROR FATAL_ERROR)
+
+# Ensure that altering a diagnostic that is still in the default state
+# uses the default state as the basis for alteration
+cmake_diagnostic(DEMOTE CMD_UNINITIALIZED WARN)
+
+cmake_diagnostic(GET CMD_UNINITIALIZED action)
+if(NOT "${action}" STREQUAL "IGNORE")
+ message(SEND_ERROR
+ "CMD_UNINITIALIZED has unexpected state '${action}' (expected 'IGNORE')"
+ )
+endif()
diff --git a/Tests/RunCMake/Diagnostics/Assertions.cmake b/Tests/RunCMake/Diagnostics/Assertions.cmake
new file mode 100644
index 0000000..c771b5b
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/Assertions.cmake
@@ -0,0 +1,19 @@
+function(expect CATEGORY EXPECTED)
+ cmake_diagnostic(GET ${CATEGORY} actual)
+ if(NOT "${actual}" STREQUAL "${EXPECTED}")
+ message(SEND_ERROR
+ "wrong action for diagnostic ${CATEGORY}"
+ " (expected '${EXPECTED}', actual '${actual}')")
+ endif()
+endfunction()
+
+function(expect_cached CATEGORY EXPECTED)
+ expect(${CATEGORY} ${EXPECTED})
+
+ if(NOT "${CATEGORY}=${EXPECTED}" IN_LIST CMAKE_DIAGNOSTIC_INIT)
+ list(JOIN CMAKE_DIAGNOSTIC_INIT ", " pretty_state)
+ message(SEND_ERROR
+ "Cached state for ${CATEGORY} missing or incorrect"
+ " (expected '${EXPECTED}' in ${pretty_state})")
+ endif()
+endfunction()
diff --git a/Tests/RunCMake/Diagnostics/CMakeLists.txt b/Tests/RunCMake/Diagnostics/CMakeLists.txt
new file mode 100644
index 0000000..d383479
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 4.3)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_DIAGNOSTIC_SCOPE)
diff --git a/Tests/RunCMake/Diagnostics/CacheInit.cmake b/Tests/RunCMake/Diagnostics/CacheInit.cmake
new file mode 100644
index 0000000..1af1495
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/CacheInit.cmake
@@ -0,0 +1,4 @@
+include(Assertions.cmake)
+
+expect(CMD_AUTHOR IGNORE)
+expect(CMD_DEPRECATED SEND_ERROR)
diff --git a/Tests/RunCMake/Diagnostics/CommandLine1.cmake b/Tests/RunCMake/Diagnostics/CommandLine1.cmake
new file mode 100644
index 0000000..72380c3
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/CommandLine1.cmake
@@ -0,0 +1,4 @@
+include(Assertions.cmake)
+
+expect_cached(CMD_AUTHOR SEND_ERROR)
+expect_cached(CMD_DEPRECATED SEND_ERROR)
diff --git a/Tests/RunCMake/Diagnostics/CommandLine2.cmake b/Tests/RunCMake/Diagnostics/CommandLine2.cmake
new file mode 100644
index 0000000..90e4741
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/CommandLine2.cmake
@@ -0,0 +1,4 @@
+include(Assertions.cmake)
+
+expect_cached(CMD_AUTHOR SEND_ERROR)
+expect_cached(CMD_DEPRECATED IGNORE)
diff --git a/Tests/RunCMake/Diagnostics/CommandLine3.cmake b/Tests/RunCMake/Diagnostics/CommandLine3.cmake
new file mode 100644
index 0000000..e11e17d
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/CommandLine3.cmake
@@ -0,0 +1,3 @@
+include(Assertions.cmake)
+
+expect_cached(CMD_UNINITIALIZED IGNORE)
diff --git a/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake b/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake
new file mode 100644
index 0000000..5ffb6fa
--- /dev/null
+++ b/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake
@@ -0,0 +1,15 @@
+include(RunCMake)
+
+run_cmake(Actions)
+
+run_cmake_with_options(
+ CacheInit
+ "-DCMAKE_DIAGNOSTIC_INIT=CMD_AUTHOR=IGNORE\;CMD_DEPRECATED=SEND_ERROR"
+)
+
+run_cmake_with_options(CommandLine1 -Wno-author -Werror=author)
+run_cmake_with_options(CommandLine1 -Werror=author)
+run_cmake_with_options(CommandLine1 -Werror=author -Wdeprecated)
+run_cmake_with_options(CommandLine1 -Wno-deprecated -Werror=author)
+run_cmake_with_options(CommandLine2 -Werror=author -Wno-deprecated)
+run_cmake_with_options(CommandLine3 -Wno-error=uninitialized)
diff --git a/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake b/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake
index f72942d..7ce5514 100644
--- a/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake
+++ b/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake
@@ -1,7 +1,7 @@
include(RunCMake)
set(common_test_options
- -Wno-dev
+ -Wno-author
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=ca494ed3-b261-4205-a01f-603c95e4cae0"
"-DCMAKE_INSTALL_SBOM_FORMATS:STRING=JSON"
"-DCMAKE_INSTALL_LIBDIR=lib"
diff --git a/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake b/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake
index 5e09f91..3447c2e 100644
--- a/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake
@@ -1,7 +1,7 @@
include(RunCMake)
set(common_test_options
- -Wno-dev
+ -Wno-author
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=ca494ed3-b261-4205-a01f-603c95e4cae0"
)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/ExternalData/BadLinkMode-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/ExternalData/BadLinkMode-result.txt
diff --git a/Tests/RunCMake/ExternalData/BadLinkMode-stderr.txt b/Tests/RunCMake/ExternalData/BadLinkMode-stderr.txt
new file mode 100644
index 0000000..29c02a2
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadLinkMode-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at .*/Modules/ExternalData\.cmake:[0-9]+ \(message\):
+ ExternalData_LINK_MODE must be `auto` or list: hardlink, symlink, copy
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/ExternalData/BadLinkModeNoSymlinks-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/ExternalData/BadLinkModeNoSymlinks-result.txt
diff --git a/Tests/RunCMake/ExternalData/BadLinkModeNoSymlinks-stderr.txt b/Tests/RunCMake/ExternalData/BadLinkModeNoSymlinks-stderr.txt
new file mode 100644
index 0000000..51f3634
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadLinkModeNoSymlinks-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at .*/Modules/ExternalData\.cmake:[0-9]+ \(message\):
+ ExternalData_LINK_MODE with `symlink` conflicts with NO_SYMLINKS
diff --git a/Tests/RunCMake/ExternalData/GoodLinkModeList-result.txt b/Tests/RunCMake/ExternalData/GoodLinkModeList-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/GoodLinkModeList-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
index b4cc95e..53c7152 100644
--- a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
@@ -1,5 +1,25 @@
include(RunCMake)
+function(run_externaldata_local test)
+ run_cmake_command(${test}
+ ${CMAKE_COMMAND}
+ -DExternalData_ACTION=local
+ -DExternalData_OBJECT_STORES=${RunCMake_BINARY_DIR}/${test}-store
+ ${ARGN}
+ -Dfile=${RunCMake_BINARY_DIR}/${test}-output.txt
+ -Dname=${RunCMake_SOURCE_DIR}/CMakeLists.txt
+ -P ${RunCMake_SOURCE_DIR}/../../../Modules/ExternalData.cmake
+ )
+endfunction()
+
+function(run_externaldata_local_link_mode test link_mode)
+ string(REPLACE ";" "\\\\;" link_mode_arg "${link_mode}")
+ run_externaldata_local(${test}
+ "-DExternalData_LINK_MODE=${link_mode_arg}"
+ ${ARGN}
+ )
+endfunction()
+
run_cmake(BadAlgoMap1)
run_cmake(BadAlgoMap2)
run_cmake(BadArguments)
@@ -8,6 +28,13 @@
run_cmake(BadCustom3)
run_cmake(BadCustom4)
run_cmake(BadHashAlgo1)
+run_externaldata_local_link_mode(BadLinkMode "invalid;copy"
+ )
+run_externaldata_local_link_mode(BadLinkModeNoSymlinks "symlink;copy"
+ -DExternalData_NO_SYMLINKS=1
+ )
+run_externaldata_local_link_mode(GoodLinkModeList "copy;hardlink"
+ )
run_cmake(BadOption1)
run_cmake(BadOption2)
run_cmake(BadRecurse1)
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-none-Debug-build-result.txt b/Tests/RunCMake/ExternalProject/GitCloneRetry-build-result.txt
similarity index 100%
copy from Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-none-Debug-build-result.txt
copy to Tests/RunCMake/ExternalProject/GitCloneRetry-build-result.txt
diff --git a/Tests/RunCMake/ExternalProject/GitCloneRetry-build-stdout.txt b/Tests/RunCMake/ExternalProject/GitCloneRetry-build-stdout.txt
new file mode 100644
index 0000000..be2ff68
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/GitCloneRetry-build-stdout.txt
@@ -0,0 +1,9 @@
+ *-- Retry #1, waiting 1 seconds before next attempt\.\.\..*
+ *-- Retry #2, waiting 1 seconds before next attempt\.\.\..*
+ *-- Retry #3, waiting 1 seconds before next attempt\.\.\..*
+ *Had to git clone more than once: 4 times\.
+ *CMake Error at [^
+]*TestGitRetry-prefix/tmp/TestGitRetry-gitclone.cmake:[0-9]+ \(message\):
+ +Failed to clone repository:[
+ ]*
+ +'[^']*/Tests/RunCMake/ExternalProject/GitCloneRetry-build/TestGitRetry.git'
diff --git a/Tests/RunCMake/ExternalProject/GitCloneRetry.cmake b/Tests/RunCMake/ExternalProject/GitCloneRetry.cmake
new file mode 100644
index 0000000..16c9dab
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/GitCloneRetry.cmake
@@ -0,0 +1,13 @@
+include(ExternalProject)
+
+set(CMAKE_EP_GIT_CLONE_RETRY_COUNT 3)
+set(CMAKE_EP_GIT_CLONE_RETRY_DELAY 1)
+
+# The GIT_REPOSITORY path does not exist, so git clone will always fail,
+# which is what triggers the retries.
+ExternalProject_Add(TestGitRetry
+ GIT_REPOSITORY "${CMAKE_CURRENT_BINARY_DIR}/TestGitRetry.git"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+)
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
index 3848d77..3e87efb 100644
--- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -258,6 +258,14 @@
run_cmake(TLSVersionBadArg)
run_cmake(TLSVersionBadVar)
run_cmake(TLSVersionBadEnv)
+
+ block()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GitCloneRetry-build)
+ run_cmake(GitCloneRetry)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ run_cmake_command(GitCloneRetry-build ${CMAKE_COMMAND} --build . --target TestGitRetry)
+ endblock()
endif()
set(RunCMake_TEST_OUTPUT_MERGE 1)
diff --git a/Tests/RunCMake/FetchContent/VarPassthroughs.cmake b/Tests/RunCMake/FetchContent/VarPassthroughs.cmake
index 284f5b8..f3bc7d0 100644
--- a/Tests/RunCMake/FetchContent/VarPassthroughs.cmake
+++ b/Tests/RunCMake/FetchContent/VarPassthroughs.cmake
@@ -8,6 +8,8 @@
set(CMAKE_NETRC DDDD)
set(CMAKE_NETRC_FILE EEEE)
set(CMAKE_TLS_VERSION FFFF)
+set(CMAKE_EP_GIT_CLONE_RETRY_COUNT GGGG)
+set(CMAKE_EP_GIT_CLONE_RETRY_DELAY HHHH)
FetchContent_Declare(PassThrough
DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed"
@@ -43,3 +45,11 @@
if(NOT contents MATCHES "CMAKE_NETRC_FILE \\[==\\[EEEE\\]==\\]")
message(FATAL_ERROR "Missing CMAKE_NETRC_FILE")
endif()
+
+if(NOT contents MATCHES "CMAKE_EP_GIT_CLONE_RETRY_COUNT \\[==\\[GGGG\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_EP_GIT_CLONE_RETRY_COUNT")
+endif()
+
+if(NOT contents MATCHES "CMAKE_EP_GIT_CLONE_RETRY_DELAY \\[==\\[HHHH\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_EP_GIT_CLONE_RETRY_DELAY")
+endif()
diff --git a/Tests/RunCMake/FileSet-SOURCES/CMakeLists.txt b/Tests/RunCMake/FileSet-SOURCES/CMakeLists.txt
new file mode 100644
index 0000000..7652e18
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 4.0)
+project(${RunCMake_TEST} LANGUAGES NONE)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/FileSet-SOURCES/CompileOptionsOrder-build-check.cmake b/Tests/RunCMake/FileSet-SOURCES/CompileOptionsOrder-build-check.cmake
new file mode 100644
index 0000000..2d73158
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/CompileOptionsOrder-build-check.cmake
@@ -0,0 +1,9 @@
+if(RunCMake_GENERATOR MATCHES "Xcode")
+ if (NOT actual_stdout MATCHES "-DOPT_SRC +-DOPT_FS")
+ set (RunCMake_TEST_FAILED "Wrong compile options order.")
+ endif()
+else()
+ if (NOT actual_stdout MATCHES "(/|-)D *OPT_TGT.+(/|-)D *OPT_SRC.+(/|-)D *OPT_FS")
+ set (RunCMake_TEST_FAILED "Wrong compile options order.")
+ endif()
+endif()
diff --git a/Tests/RunCMake/FileSet-SOURCES/CompileOptionsOrder.cmake b/Tests/RunCMake/FileSet-SOURCES/CompileOptionsOrder.cmake
new file mode 100644
index 0000000..66fe7ef
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/CompileOptionsOrder.cmake
@@ -0,0 +1,15 @@
+enable_language(C)
+
+set(CMAKE_VERBOSE_MAKEFILE ON)
+set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS OFF)
+# ensure no temp file will be used
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+
+add_library(lib1 STATIC)
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib1.c)
+
+set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_FS)
+
+set_property(TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_TGT)
+set_property(SOURCE lib1.c PROPERTY COMPILE_OPTIONS -DOPT_SRC)
diff --git a/Tests/RunCMake/FileSet-SOURCES/CustomCommandInput.cmake b/Tests/RunCMake/FileSet-SOURCES/CustomCommandInput.cmake
new file mode 100644
index 0000000..2ab3b26
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/CustomCommandInput.cmake
@@ -0,0 +1,10 @@
+
+enable_language(C)
+
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/custom.c"
+ COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/lib1.c"
+ "${CMAKE_CURRENT_BINARY_DIR}/custom.c")
+
+add_library(lib1 STATIC)
+target_sources(lib1 PRIVATE FILE_SET SOURCES BASE_DIRS "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/custom.c")
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/FileSet-SOURCES/FileNoExist-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/FileSet-SOURCES/FileNoExist-result.txt
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileNoExist-stderr.txt b/Tests/RunCMake/FileSet-SOURCES/FileNoExist-stderr.txt
new file mode 100644
index 0000000..4e566b3
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileNoExist-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at FileNoExist\.cmake:[0-9]+ \(target_sources\):
+ Cannot find source file:
+
+ .+/Tests/RunCMake/FileSet-SOURCES/noexist\.c
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileNoExist.cmake b/Tests/RunCMake/FileSet-SOURCES/FileNoExist.cmake
new file mode 100644
index 0000000..c25cba2
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileNoExist.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_library(lib1 STATIC lib1.c)
+target_sources(lib1 PRIVATE FILE_SET SOURCES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES noexist.c)
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetExport.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetExport.cmake
new file mode 100644
index 0000000..9f50867
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetExport.cmake
@@ -0,0 +1,40 @@
+enable_language(C)
+
+add_library(lib1 STATIC)
+target_sources(lib1 PRIVATE lib1.c)
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
+
+set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/subdir1>"
+ "$<INSTALL_INTERFACE:include/subdir1>")
+
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/subdir2>"
+ "$<INSTALL_INTERFACE:include/subdir2>")
+
+target_sources(lib1 PUBLIC FILE_SET SOURCES FILES lib5.c)
+
+set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_SRCS)
+set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_LIB1_SRCS)
+set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/srcs>"
+ "$<INSTALL_INTERFACE:include/srcs>")
+
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE lib1)
+target_compile_definitions(main PRIVATE CONSUMER)
+
+if(CMAKE_GENERATOR MATCHES "Xcode")
+ install(TARGETS lib1 EXPORT export FILE_SET a DESTINATION sources
+ FILE_SET SOURCES DESTINATION sources/srcs)
+else()
+ install(TARGETS lib1 EXPORT export FILE_SET a DESTINATION sources
+ FILE_SET SOURCES DESTINATION sources/$<IF:$<CONFIG:Debug>,debug,release>)
+endif()
+install(FILES subdir1/h1.h subdir1/h3.h DESTINATION include/subdir1)
+install(FILES subdir2/h2.h subdir2/h3.h DESTINATION include/subdir2)
+
+install(EXPORT export FILE export.cmake NAMESPACE install:: DESTINATION lib/cmake)
+export(EXPORT export FILE export.cmake NAMESPACE export::)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/FileSet-SOURCES/FileSetFramework1-result.txt
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1-stderr.txt b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1-stderr.txt
new file mode 100644
index 0000000..5c54059
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error in CMakeLists\.txt:
+ The file set "HEADERS", of type "HEADERS", is incompatible with the
+ "FRAMEWORK" target "lib1"\.
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1.cmake
new file mode 100644
index 0000000..7c166a0
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework1.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_library(lib1 SHARED)
+target_sources(lib1
+ PUBLIC FILE_SET SOURCES FILES lib1.c
+ FILE_SET HEADERS FILES lib1.h
+ )
+set_property(TARGET lib1 PROPERTY FRAMEWORK ON)
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetFramework2.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework2.cmake
new file mode 100644
index 0000000..f577381
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetFramework2.cmake
@@ -0,0 +1,7 @@
+enable_language(C)
+
+add_library(lib1 SHARED)
+target_sources(lib1
+ PUBLIC FILE_SET SOURCES FILES lib1.c
+ )
+set_property(TARGET lib1 PROPERTY FRAMEWORK ON)
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetImport.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetImport.cmake
new file mode 100644
index 0000000..53264cf
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetImport.cmake
@@ -0,0 +1,85 @@
+enable_language(C)
+
+get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+
+function(assert_target_prop_eq tgt prop value)
+ unset(actual_value)
+ get_property(actual_value TARGET ${tgt} PROPERTY ${prop})
+ if(NOT actual_value STREQUAL value)
+ message(SEND_ERROR "Expected value of target ${prop}:\n ${value}\nActual value:\n ${actual_value}")
+ endif()
+endfunction()
+
+function(assert_fileset_prop_eq tgt fs prop value)
+ unset(actual_value)
+ get_property(actual_value FILE_SET ${fs} TARGET ${tgt} PROPERTY ${prop})
+ if(NOT actual_value STREQUAL value)
+ message(SEND_ERROR "Expected value of file set ${prop}:\n ${value}\nActual value:\n ${actual_value}")
+ endif()
+endfunction()
+
+cmake_path(GET CMAKE_BINARY_DIR PARENT_PATH export_build_dir)
+cmake_path(APPEND export_build_dir "FileSetExport-build")
+
+if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_EQUAL 4.3
+ AND NOT CMAKE_PATCH_VERSION VERSION_LESS 20000000)
+ # development version for future 4.4: Force version 4.4
+ set(CMAKE_VERSION_BACKUP "${CMAKE_VERSION}")
+ set(CMAKE_VERSION 4.4)
+endif()
+include("${export_build_dir}/export.cmake")
+include("${export_build_dir}/install/lib/cmake/export.cmake")
+if(CMAKE_VERSION VERSION_GREATER 4.3 AND CMAKE_VERSION VERSION_LESS 4.4
+ AND NOT CMake_VERSION_PATCH VERSION_LESS 20000000)
+ # development version for future 4.4: Force version 4.4
+ set(CMAKE_VERSION "${CMAKE_VERSION_BACKUP}")
+endif()
+
+
+assert_target_prop_eq(export::lib1 SOURCE_SETS "")
+assert_target_prop_eq(export::lib1 INTERFACE_SOURCE_SETS "a;SOURCES")
+assert_target_prop_eq(export::lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib2.c")
+assert_target_prop_eq(export::lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
+assert_target_prop_eq(export::lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
+
+assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_A")
+assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_A")
+assert_fileset_prop_eq(export::lib1 a INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
+
+assert_fileset_prop_eq(export::lib1 SOURCES INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_SRCS")
+assert_fileset_prop_eq(export::lib1 SOURCES INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_SRCS")
+assert_fileset_prop_eq(export::lib1 SOURCES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/srcs")
+
+
+assert_target_prop_eq(install::lib1 SOURCE_SETS "")
+assert_target_prop_eq(install::lib1 INTERFACE_SOURCE_SETS "a;SOURCES")
+assert_target_prop_eq(install::lib1 SOURCE_SET_a "${export_build_dir}/install/sources/lib2.c")
+if(multi_config)
+ if(CMAKE_GENERATOR MATCHES "Xcode")
+ assert_target_prop_eq(install::lib1 SOURCE_SET "${export_build_dir}/install/sources/srcs/lib5.c")
+ assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "${export_build_dir}/install/sources/srcs/lib5.c")
+ else()
+ assert_target_prop_eq(install::lib1 SOURCE_SET "$<$<CONFIG:Debug>:${export_build_dir}/install/sources/debug/lib5.c>;$<$<CONFIG:Release>:${export_build_dir}/install/sources/release/lib5.c>")
+ assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "$<$<CONFIG:Debug>:${export_build_dir}/install/sources/debug/lib5.c>;$<$<CONFIG:Release>:${export_build_dir}/install/sources/release/lib5.c>")
+ endif()
+else()
+ assert_target_prop_eq(install::lib1 SOURCE_SET "${export_build_dir}/install/sources/debug/lib5.c")
+ assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "${export_build_dir}/install/sources/debug/lib5.c")
+endif()
+
+assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_A")
+assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_A")
+assert_fileset_prop_eq(install::lib1 a INTERFACE_INCLUDE_DIRECTORIES "${export_build_dir}/install/include/subdir2")
+
+assert_fileset_prop_eq(install::lib1 SOURCES INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_SRCS")
+assert_fileset_prop_eq(install::lib1 SOURCES INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_SRCS")
+assert_fileset_prop_eq(install::lib1 SOURCES INTERFACE_INCLUDE_DIRECTORIES "${export_build_dir}/install/include/srcs")
+
+
+add_executable(main_export main.c)
+target_link_libraries(main_export PRIVATE export::lib1)
+target_compile_definitions(main_export PRIVATE CONSUMER)
+
+add_executable(main_install main.c)
+target_link_libraries(main_install PRIVATE install::lib1)
+target_compile_definitions(main_install PRIVATE CONSUMER)
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetProperties.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties.cmake
new file mode 100644
index 0000000..b463914
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties.cmake
@@ -0,0 +1,19 @@
+enable_language(C)
+
+add_library(lib1 STATIC)
+target_sources(lib1 PRIVATE lib1.c)
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
+
+set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
+
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE lib1)
+target_compile_definitions(main PRIVATE CONSUMER)
+
+add_library(lib2 SHARED)
+target_link_libraries(lib2 PRIVATE lib1)
+target_compile_definitions(lib2 PRIVATE CONSUMER)
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2-lib1-check.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2-lib1-check.cmake
new file mode 100644
index 0000000..2705cba
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2-lib1-check.cmake
@@ -0,0 +1,4 @@
+
+if (NOT actual_stdout MATCHES "(/|-)D *OPT_FS" OR actual_stdout MATCHES "(/|-)D *OPT_INTERFACE_FS")
+ set (RunCMake_TEST_FAILED "Wrong compile options specified.")
+endif()
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2-main-check.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2-main-check.cmake
new file mode 100644
index 0000000..1637d27
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2-main-check.cmake
@@ -0,0 +1,4 @@
+
+if (NOT actual_stdout MATCHES "(/|-)D *OPT_INTERFACE_FS" OR actual_stdout MATCHES "(/|-)D *OPT_FS")
+ set (RunCMake_TEST_FAILED "Wrong compile options specified.")
+endif()
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2.cmake
new file mode 100644
index 0000000..79cfe58
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetProperties2.cmake
@@ -0,0 +1,17 @@
+enable_language(C)
+
+set(CMAKE_VERBOSE_MAKEFILE ON)
+set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS OFF)
+# ensure no temp file will be used
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+
+add_library(lib1 STATIC)
+target_sources(lib1 PRIVATE lib1.c)
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib4.c)
+
+set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_FS)
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_FS)
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE lib1)
diff --git a/Tests/RunCMake/FileSet-SOURCES/FileSetTransitivity.cmake b/Tests/RunCMake/FileSet-SOURCES/FileSetTransitivity.cmake
new file mode 100644
index 0000000..0a8f724
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/FileSetTransitivity.cmake
@@ -0,0 +1,17 @@
+enable_language(C)
+
+add_library(lib1 STATIC)
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
+
+set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
+
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
+set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
+
+add_library(lib2 STATIC lib1.c)
+target_link_libraries(lib2 INTERFACE lib1)
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE lib2)
+target_compile_definitions(main PRIVATE CONSUMER)
diff --git a/Tests/RunCMake/FileSet-SOURCES/IncludeDirectoriesOrder.cmake b/Tests/RunCMake/FileSet-SOURCES/IncludeDirectoriesOrder.cmake
new file mode 100644
index 0000000..80a2767
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/IncludeDirectoriesOrder.cmake
@@ -0,0 +1,11 @@
+enable_language(C)
+
+add_library(lib1 STATIC)
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib3.c)
+
+set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/dir")
+
+if(NOT CMAKE_GENERATOR MATCHES "Xcode")
+ set_property(TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
+endif()
+set_property(SOURCE lib3.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
diff --git a/Tests/RunCMake/FileSet-SOURCES/IndependentFiles-check.cmake b/Tests/RunCMake/FileSet-SOURCES/IndependentFiles-check.cmake
new file mode 100644
index 0000000..748665a
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/IndependentFiles-check.cmake
@@ -0,0 +1,4 @@
+if (EXISTS "${RunCMake_TEST_BINARY_DIR}/gen.c")
+ list(APPEND RunCMake_TEST_FAILED
+ "The `gen.c` file should not be generated to compile `unrelated`'s object")
+endif ()
diff --git a/Tests/RunCMake/FileSet-SOURCES/IndependentFiles.cmake b/Tests/RunCMake/FileSet-SOURCES/IndependentFiles.cmake
new file mode 100644
index 0000000..821270d
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/IndependentFiles.cmake
@@ -0,0 +1,16 @@
+
+enable_language(C)
+
+set(CACHE{CMAKE_INTERMEDIATE_DIR_STRATEGY} TYPE STRING FORCE VALUE FULL)
+
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gen.c"
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/gen.c.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/gen.c"
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/gen.c.in")
+
+add_library(lib1 STATIC)
+target_sources(lib1 PRIVATE independent.c
+ PRIVATE FILE_SET SOURCES BASE_DIRS "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/gen.c")
+
+set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INDEPENDENT_FILES ON)
diff --git a/Tests/RunCMake/FileSet-SOURCES/IndependentFilesWarning-stderr.txt b/Tests/RunCMake/FileSet-SOURCES/IndependentFilesWarning-stderr.txt
new file mode 100644
index 0000000..1c4e572
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/IndependentFilesWarning-stderr.txt
@@ -0,0 +1,5 @@
+CMake Warning \(dev\) in CMakeLists\.txt:
+ the "INDEPENDENT_FILES" property of the file set "HEADERS" of the target
+ "lib1" will be ignored because it is incompatible with the file set type
+ "HEADERS"\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/FileSet-SOURCES/IndependentFilesWarning.cmake b/Tests/RunCMake/FileSet-SOURCES/IndependentFilesWarning.cmake
new file mode 100644
index 0000000..acfed11
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/IndependentFilesWarning.cmake
@@ -0,0 +1,13 @@
+
+enable_language(C)
+
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gen.h"
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/gen.c.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/gen.h"
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/gen.c.in")
+
+add_library(lib1 STATIC lib1.c)
+target_sources(lib1 PRIVATE FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/gen.h")
+
+set_property(FILE_SET HEADERS TARGET lib1 PROPERTY INDEPENDENT_FILES ON)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface-result.txt
diff --git a/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface-stderr.txt b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface-stderr.txt
new file mode 100644
index 0000000..62bef3e
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at InstallMissingSetsInterface\.cmake:[0-9]+ \(install\):
+ install TARGETS target lib1 is exported but not all of its interface file
+ sets are installed
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface.cmake b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface.cmake
new file mode 100644
index 0000000..9567291
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterface.cmake
@@ -0,0 +1,5 @@
+enable_language(C)
+
+add_library(lib1 STATIC)
+target_sources(lib1 INTERFACE FILE_SET a TYPE SOURCES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES lib1.c)
+install(TARGETS lib1 EXPORT a)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall-result.txt
diff --git a/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall-stderr.txt b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall-stderr.txt
new file mode 100644
index 0000000..948dbf7
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error in CMakeLists\.txt:
+ File set "a" is listed in interface file sets of lib1 but has not been
+ exported
+
+
+CMake Generate step failed\. Build files cannot be regenerated correctly\.
diff --git a/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall.cmake b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall.cmake
new file mode 100644
index 0000000..b3c2476
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/InstallMissingSetsInterfacePostInstall.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+add_library(lib1 STATIC)
+install(TARGETS lib1 EXPORT a)
+target_sources(lib1 INTERFACE FILE_SET a TYPE SOURCES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES lib1.c)
+install(EXPORT a DESTINATION lib/cmake/test)
diff --git a/Tests/RunCMake/FileSet-SOURCES/RunCMakeTest.cmake b/Tests/RunCMake/FileSet-SOURCES/RunCMakeTest.cmake
new file mode 100644
index 0000000..2e2c265
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/RunCMakeTest.cmake
@@ -0,0 +1,107 @@
+
+include(RunCMake)
+
+function(run_and_build test)
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(config_options "-DCMAKE_CONFIGURATION_TYPES=Debug")
+ else()
+ set(config_options -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ set(RunCMake_TEST_OPTIONS ${config_options})
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${test}-build")
+ run_cmake_with_options(${test})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ if(ARGN)
+ foreach(target IN LISTS ARGN)
+ run_cmake_command(${test}-${target} ${CMAKE_COMMAND} --build . --config Debug --target ${target} --verbose)
+ endforeach()
+ else()
+ run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Debug --verbose)
+ endif()
+endfunction()
+
+function(run_and_check test)
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ run_and_build(${test} ${ARGN})
+endfunction()
+
+
+run_cmake(FileNoExist)
+run_cmake(TargetProperties)
+
+run_and_build(FileSetProperties)
+run_and_build(CustomCommandInput)
+run_and_build(IncludeDirectoriesOrder)
+run_and_build(FileSetTransitivity)
+run_and_check(CompileOptionsOrder)
+if(APPLE)
+ run_cmake(FileSetFramework1)
+ run_and_build(FileSetFramework2)
+endif()
+if (RunCMake_GENERATOR MATCHES "Ninja")
+ run_cmake(IndependentFilesWarning)
+ if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(IndependentFiles_target "CMakeFiles/lib1.dir/Debug/independent.c${CMAKE_C_OUTPUT_EXTENSION}")
+ else ()
+ set(IndependentFiles_target "CMakeFiles/lib1.dir/independent.c${CMAKE_C_OUTPUT_EXTENSION}")
+ endif ()
+ set(RunCMake-check-file IndependentFiles-check.cmake)
+ run_and_build(IndependentFiles ${IndependentFiles_target})
+endif()
+
+# Some environments are excluded because they are not able to honor verbose mode
+if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode"
+ OR (RunCMake_GENERATOR MATCHES "Visual Studio" AND MSVC_VERSION GREATER_EQUAL "1600"))
+ AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
+ run_and_check(FileSetProperties2 lib1 main)
+endif()
+
+function(run_export_import name)
+ if(ARGV1)
+ set(importname ${ARGV1})
+ else()
+ set(importname ${name})
+ endif()
+
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(_config_options "-DCMAKE_CONFIGURATION_TYPES=Debug\\\\;Release")
+ else()
+ set(_config_options -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}Export-build")
+ set(RunCMake_TEST_OPTIONS "--install-prefix=${RunCMake_TEST_BINARY_DIR}/install" ${_config_options})
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${name}Export)
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ run_cmake_command(${name}Export-build-Debug ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${name}Export-install-Debug ${CMAKE_COMMAND} --install . --config Debug)
+ run_cmake_command(${name}Export-build-Release ${CMAKE_COMMAND} --build . --config Release)
+ run_cmake_command(${name}Export-install-Release ${CMAKE_COMMAND} --install . --config Release)
+ else()
+ run_cmake_command(${name}Export-build ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${name}Export-install ${CMAKE_COMMAND} --install . --config Debug)
+ endif()
+ unset(RunCMake_TEST_OPTIONS)
+
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${importname}Import-build")
+ unset(RunCMake_TEST_OPTIONS)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${importname}Import)
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ run_cmake_command(${importname}Import-build-Debug ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${importname}Import-build-Release ${CMAKE_COMMAND} --build . --config Release)
+ else()
+ run_cmake_command(${importname}Import-build ${CMAKE_COMMAND} --build . --config Debug)
+ endif()
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endfunction()
+
+run_cmake(InstallMissingSetsInterface)
+run_cmake(InstallMissingSetsInterfacePostInstall)
+run_export_import(FileSet)
diff --git a/Tests/RunCMake/FileSet-SOURCES/TargetProperties.cmake b/Tests/RunCMake/FileSet-SOURCES/TargetProperties.cmake
new file mode 100644
index 0000000..2b8d180
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/TargetProperties.cmake
@@ -0,0 +1,61 @@
+enable_language(C)
+
+function(assert_prop_undef tgt prop)
+ unset(actual_value)
+ get_property(actual_value TARGET ${tgt} PROPERTY ${prop})
+ if(DEFINED actual_value)
+ message(SEND_ERROR "${prop} should be undefined, actual value:\n ${actual_value}")
+ endif()
+endfunction()
+
+function(assert_prop_eq tgt prop value)
+ unset(actual_value)
+ get_property(actual_value TARGET ${tgt} PROPERTY ${prop})
+ if(NOT actual_value STREQUAL value)
+ message(SEND_ERROR "Expected value of ${prop}:\n ${value}\nActual value:\n ${actual_value}")
+ endif()
+endfunction()
+
+add_library(lib1 STATIC)
+assert_prop_eq(lib1 SOURCE_SETS "")
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "")
+
+target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES BASE_DIRS "." FILES lib1.c lib2.c)
+assert_prop_eq(lib1 SOURCE_SETS "a")
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a")
+assert_prop_eq(lib1 SOURCE_DIRS_a "${CMAKE_CURRENT_SOURCE_DIR}/.")
+assert_prop_eq(lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib1.c;${CMAKE_CURRENT_SOURCE_DIR}/lib2.c")
+
+target_sources(lib1 PUBLIC FILE_SET a FILES lib3.c)
+assert_prop_eq(lib1 SOURCE_SETS "a")
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a")
+assert_prop_eq(lib1 SOURCE_DIRS_a "${CMAKE_CURRENT_SOURCE_DIR}/.")
+assert_prop_eq(lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib1.c;${CMAKE_CURRENT_SOURCE_DIR}/lib2.c;${CMAKE_CURRENT_SOURCE_DIR}/lib3.c")
+
+target_sources(lib1 PRIVATE FILE_SET b TYPE SOURCES BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/dir" FILES dir/dir.c)
+assert_prop_eq(lib1 SOURCE_SETS "a;b")
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a")
+assert_prop_eq(lib1 SOURCE_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR}/dir")
+assert_prop_eq(lib1 SOURCE_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/dir/dir.c")
+
+target_sources(lib1 INTERFACE FILE_SET c TYPE SOURCES FILE_SET d TYPE SOURCES)
+assert_prop_eq(lib1 SOURCE_SETS "a;b")
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a;c;d")
+assert_prop_eq(lib1 SOURCE_DIRS_c "${CMAKE_CURRENT_SOURCE_DIR}")
+assert_prop_eq(lib1 SOURCE_SET_c "")
+assert_prop_eq(lib1 SOURCE_DIRS_d "${CMAKE_CURRENT_SOURCE_DIR}")
+assert_prop_eq(lib1 SOURCE_SET_d "")
+
+target_sources(lib1 PUBLIC FILE_SET SOURCES BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES lib4.c)
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a;c;d;SOURCES")
+assert_prop_eq(lib1 SOURCE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
+assert_prop_eq(lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c")
+assert_prop_eq(lib1 SOURCE_DIRS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
+assert_prop_eq(lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c")
+
+target_sources(lib1 PUBLIC FILE_SET SOURCES FILES lib5.c)
+assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a;c;d;SOURCES")
+assert_prop_eq(lib1 SOURCE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
+assert_prop_eq(lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c;${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
+assert_prop_eq(lib1 SOURCE_DIRS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
+assert_prop_eq(lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c;${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
diff --git a/Tests/RunCMake/FileSet-SOURCES/dir/dir.c b/Tests/RunCMake/FileSet-SOURCES/dir/dir.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/dir/dir.c
diff --git a/Tests/RunCMake/FileSet-SOURCES/dir/h3.h b/Tests/RunCMake/FileSet-SOURCES/dir/h3.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/dir/h3.h
diff --git a/Tests/RunCMake/FileSet-SOURCES/gen.c.in b/Tests/RunCMake/FileSet-SOURCES/gen.c.in
new file mode 100644
index 0000000..caf53fe
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/gen.c.in
@@ -0,0 +1,4 @@
+
+void gen(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/independent.c b/Tests/RunCMake/FileSet-SOURCES/independent.c
new file mode 100644
index 0000000..f061210
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/independent.c
@@ -0,0 +1,4 @@
+
+void independent(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/lib1.c b/Tests/RunCMake/FileSet-SOURCES/lib1.c
new file mode 100644
index 0000000..950c340
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/lib1.c
@@ -0,0 +1,14 @@
+
+#if defined(INTERFACE_LIB1_A)
+# error "INTERFACE_LIB1_A defined"
+#endif
+#if defined(LIB1_A)
+# error "LIB1_A defined"
+#endif
+#if defined(CONSUMER)
+# error "CONSUMER defined"
+#endif
+
+void f1(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/lib1.h b/Tests/RunCMake/FileSet-SOURCES/lib1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/lib1.h
diff --git a/Tests/RunCMake/FileSet-SOURCES/lib2.c b/Tests/RunCMake/FileSet-SOURCES/lib2.c
new file mode 100644
index 0000000..f216e2a
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/lib2.c
@@ -0,0 +1,24 @@
+
+#if defined(CONSUMER)
+# if defined(LIB1_A)
+# error "LIB1_A defined"
+# endif
+# if !defined(INTERFACE_LIB1_A)
+# error "INTERFACE_LIB1_A not defined"
+# endif
+
+# include "h2.h"
+#else
+# if !defined(LIB1_A)
+# error "LIB1_A not defined"
+# endif
+# if defined(INTERFACE_LIB1_A)
+# error "INTERFACE_LIB1_A defined"
+# endif
+
+# include "h1.h"
+#endif
+
+void f2(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/lib3.c b/Tests/RunCMake/FileSet-SOURCES/lib3.c
new file mode 100644
index 0000000..edb0abb
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/lib3.c
@@ -0,0 +1,7 @@
+
+
+#include "h3.h"
+
+void f3(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/lib4.c b/Tests/RunCMake/FileSet-SOURCES/lib4.c
new file mode 100644
index 0000000..bbac37d
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/lib4.c
@@ -0,0 +1,4 @@
+
+void f2(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/lib5.c b/Tests/RunCMake/FileSet-SOURCES/lib5.c
new file mode 100644
index 0000000..431805c
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/lib5.c
@@ -0,0 +1,4 @@
+
+void f5(void)
+{
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/main.c b/Tests/RunCMake/FileSet-SOURCES/main.c
new file mode 100644
index 0000000..6666e93
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/main.c
@@ -0,0 +1,9 @@
+
+extern void f2(void);
+
+int main(void)
+{
+ f2();
+
+ return 0;
+}
diff --git a/Tests/RunCMake/FileSet-SOURCES/subdir1/h1.h b/Tests/RunCMake/FileSet-SOURCES/subdir1/h1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/subdir1/h1.h
diff --git a/Tests/RunCMake/FileSet-SOURCES/subdir1/h3.h b/Tests/RunCMake/FileSet-SOURCES/subdir1/h3.h
new file mode 100644
index 0000000..5ef3114
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/subdir1/h3.h
@@ -0,0 +1,2 @@
+
+#error "TARGET INCLUDE_DIRECTORIES"
diff --git a/Tests/RunCMake/FileSet-SOURCES/subdir2/h2.h b/Tests/RunCMake/FileSet-SOURCES/subdir2/h2.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/subdir2/h2.h
diff --git a/Tests/RunCMake/FileSet-SOURCES/subdir2/h3.h b/Tests/RunCMake/FileSet-SOURCES/subdir2/h3.h
new file mode 100644
index 0000000..40a6150
--- /dev/null
+++ b/Tests/RunCMake/FileSet-SOURCES/subdir2/h3.h
@@ -0,0 +1,2 @@
+
+#error "SOURCE INCLUDE_DIRECTORIES"
diff --git a/Tests/RunCMake/FileSetProperties/BASE_DIRS.cmake b/Tests/RunCMake/FileSetProperties/BASE_DIRS.cmake
new file mode 100644
index 0000000..4ca91c6
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/BASE_DIRS.cmake
@@ -0,0 +1,21 @@
+
+enable_language(C)
+
+add_library(foo STATIC foo.c)
+
+
+target_sources(foo PUBLIC FILE_SET HEADERS FILES foo.h)
+
+get_property(dirs FILE_SET HEADERS TARGET foo PROPERTY BASE_DIRS)
+if(NOT dirs STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ message(SEND_ERROR "wrong base dirs: '${dirs}' instead of '${CMAKE_CURRENT_SOURCE_DIR}'")
+endif()
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/foo.h" "")
+set_property(FILE_SET HEADERS TARGET foo PROPERTY BASE_DIRS "${CMAKE_CURRENT_BINARY_DIR}")
+set_property(FILE_SET HEADERS TARGET foo PROPERTY SOURCES "${CMAKE_CURRENT_BINARY_DIR}/foo.h")
+
+get_property(dirs FILE_SET HEADERS TARGET foo PROPERTY BASE_DIRS)
+if(NOT dirs STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
+ message(SEND_ERROR "wrong base dirs: '${dirs}' instead of '${CMAKE_CURRENT_BINARY_DIR}'")
+endif()
diff --git a/Tests/RunCMake/FileSetProperties/CMakeLists.txt b/Tests/RunCMake/FileSetProperties/CMakeLists.txt
new file mode 100644
index 0000000..6e44ef5
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 4.3)
+project(${RunCMake_TEST})
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-result.txt b/Tests/RunCMake/FileSetProperties/ReadOnly-Properties-result.txt
similarity index 100%
copy from Tests/RunCMake/target_sources/FileSetFramework-result.txt
copy to Tests/RunCMake/FileSetProperties/ReadOnly-Properties-result.txt
diff --git a/Tests/RunCMake/FileSetProperties/ReadOnly-Properties-stderr.txt b/Tests/RunCMake/FileSetProperties/ReadOnly-Properties-stderr.txt
new file mode 100644
index 0000000..f57079f
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/ReadOnly-Properties-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at ReadOnly-Properties\.cmake:[0-9]+ \(set_property\):
+ TYPE property is read-only for the file set "HEADERS of the target "foo"
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at ReadOnly-Properties\.cmake:[0-9]+ \(set_property\):
+ SCOPE property is read-only for the file set "HEADERS of the target "foo"
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/FileSetProperties/ReadOnly-Properties.cmake b/Tests/RunCMake/FileSetProperties/ReadOnly-Properties.cmake
new file mode 100644
index 0000000..3113824
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/ReadOnly-Properties.cmake
@@ -0,0 +1,7 @@
+
+add_library(foo STATIC)
+
+target_sources(foo PUBLIC FILE_SET HEADERS)
+
+set_property(FILE_SET HEADERS TARGET foo PROPERTY TYPE CXX_MODULES)
+set_property(FILE_SET HEADERS TARGET foo PROPERTY SCOPE PRIVATE)
diff --git a/Tests/RunCMake/FileSetProperties/RunCMakeTest.cmake b/Tests/RunCMake/FileSetProperties/RunCMakeTest.cmake
new file mode 100644
index 0000000..e52ce14
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/RunCMakeTest.cmake
@@ -0,0 +1,8 @@
+include(RunCMake)
+
+run_cmake(ReadOnly-Properties)
+
+run_cmake(TYPE)
+run_cmake(SCOPE)
+run_cmake(SOURCES)
+run_cmake(BASE_DIRS)
diff --git a/Tests/RunCMake/FileSetProperties/SCOPE.cmake b/Tests/RunCMake/FileSetProperties/SCOPE.cmake
new file mode 100644
index 0000000..cc58aa7
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/SCOPE.cmake
@@ -0,0 +1,10 @@
+
+enable_language(C)
+
+add_library(foo STATIC foo.c)
+target_sources(foo PUBLIC FILE_SET HEADERS FILES foo.h)
+
+get_property(scope FILE_SET HEADERS TARGET foo PROPERTY SCOPE)
+if(NOT scope STREQUAL "PUBLIC")
+ message(SEND_ERROR "wrong scope: ${scope} instead of PUBLIC")
+endif()
diff --git a/Tests/RunCMake/FileSetProperties/SOURCES.cmake b/Tests/RunCMake/FileSetProperties/SOURCES.cmake
new file mode 100644
index 0000000..c6b36cf
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/SOURCES.cmake
@@ -0,0 +1,112 @@
+
+enable_language(C)
+
+add_library(foo STATIC foo.c)
+
+
+target_sources(foo PUBLIC FILE_SET HEADERS FILES foo.h)
+
+get_property(srcs FILE_SET HEADERS TARGET foo PROPERTY SOURCES)
+if(NOT srcs MATCHES ".*/foo.h$")
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of 'foo.h'")
+endif()
+get_property(srcs FILE_SET HEADERS TARGET foo PROPERTY INTERFACE_SOURCES)
+if(NOT srcs MATCHES ".*/foo.h$")
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of 'foo.h'")
+endif()
+
+
+set_property(FILE_SET HEADERS TARGET foo PROPERTY SOURCES bar.h)
+
+get_property(srcs FILE_SET HEADERS TARGET foo PROPERTY SOURCES)
+if(NOT srcs MATCHES "[^;]*bar.h$")
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of 'bar.h'")
+endif()
+get_property(srcs FILE_SET HEADERS TARGET foo PROPERTY INTERFACE_SOURCES)
+if(NOT srcs MATCHES "[^;]*bar.h$")
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of 'bar.h'")
+endif()
+
+
+set_property(FILE_SET HEADERS TARGET foo APPEND PROPERTY SOURCES foo.h)
+
+get_property(srcs FILE_SET HEADERS TARGET foo PROPERTY SOURCES)
+if(NOT srcs MATCHES "[^;]*bar.h;[^;]*foo.h$")
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of 'foo.h;bar.h'")
+endif()
+get_property(srcs FILE_SET HEADERS TARGET foo PROPERTY INTERFACE_SOURCES)
+if(NOT srcs MATCHES "[^;]*bar.h;[^;]*foo.h$")
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of 'foo.h;bar.h'")
+endif()
+
+
+target_sources(foo PRIVATE FILE_SET foo TYPE HEADERS FILES h1.h)
+
+get_property(srcs FILE_SET foo TARGET foo PROPERTY SOURCES)
+if(NOT srcs MATCHES ".*/h1.h$")
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of 'h1.h'")
+endif()
+get_property(srcs FILE_SET foo TARGET foo PROPERTY INTERFACE_SOURCES)
+if(srcs)
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of empty list")
+endif()
+
+
+set_property(FILE_SET foo TARGET foo PROPERTY SOURCES h2.h)
+
+get_property(srcs FILE_SET foo TARGET foo PROPERTY SOURCES)
+if(NOT srcs MATCHES "[^;]*h2.h$")
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of 'h2.h'")
+endif()
+get_property(srcs FILE_SET foo TARGET foo PROPERTY INTERFACE_SOURCES)
+if(srcs)
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of empty list")
+endif()
+
+
+set_property(FILE_SET foo TARGET foo PROPERTY INTERFACE_SOURCES h2.h)
+
+get_property(srcs FILE_SET foo TARGET foo PROPERTY SOURCES)
+if(NOT srcs MATCHES "[^;]*h2.h$")
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of 'h2.h'")
+endif()
+get_property(srcs FILE_SET foo TARGET foo PROPERTY INTERFACE_SOURCES)
+if(srcs)
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of empty list")
+endif()
+
+
+target_sources(foo INTERFACE FILE_SET bar TYPE HEADERS FILES foo.h)
+
+get_property(srcs FILE_SET bar TARGET foo PROPERTY SOURCES)
+if(srcs)
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of empty list")
+endif()
+get_property(srcs FILE_SET bar TARGET foo PROPERTY INTERFACE_SOURCES)
+if(NOT srcs MATCHES "[^;]*/foo.h$")
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of 'foo.h'")
+endif()
+
+
+set_property(FILE_SET bar TARGET foo PROPERTY INTERFACE_SOURCES bar.h)
+
+get_property(srcs FILE_SET bar TARGET foo PROPERTY SOURCES)
+if(srcs)
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of empty list")
+endif()
+get_property(srcs FILE_SET bar TARGET foo PROPERTY INTERFACE_SOURCES)
+if(NOT srcs MATCHES "[^;]*bar.h$")
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of 'bar.h'")
+endif()
+
+
+set_property(FILE_SET bar TARGET foo PROPERTY SOURCES foo.h)
+
+get_property(srcs FILE_SET bar TARGET foo PROPERTY SOURCES)
+if(srcs)
+ message(SEND_ERROR "wrong sources: '${srcs}' instead of empty list")
+endif()
+get_property(srcs FILE_SET bar TARGET foo PROPERTY INTERFACE_SOURCES)
+if(NOT srcs MATCHES "[^;]*bar.h$")
+ message(SEND_ERROR "wrong interface sources: '${srcs}' instead of 'bar.h'")
+endif()
diff --git a/Tests/RunCMake/FileSetProperties/TYPE.cmake b/Tests/RunCMake/FileSetProperties/TYPE.cmake
new file mode 100644
index 0000000..c3026f8
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/TYPE.cmake
@@ -0,0 +1,10 @@
+
+enable_language(C)
+
+add_library(foo STATIC foo.c)
+target_sources(foo PUBLIC FILE_SET HEADERS FILES foo.h)
+
+get_property(type FILE_SET HEADERS TARGET foo PROPERTY TYPE)
+if(NOT type STREQUAL "HEADERS")
+ message(SEND_ERROR "wrong type: ${type} instead of HEADERS")
+endif()
diff --git a/Tests/RunCMake/FileSetProperties/bar.h b/Tests/RunCMake/FileSetProperties/bar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/bar.h
diff --git a/Tests/RunCMake/FileSetProperties/foo.c b/Tests/RunCMake/FileSetProperties/foo.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/foo.c
diff --git a/Tests/RunCMake/FileSetProperties/foo.h b/Tests/RunCMake/FileSetProperties/foo.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/foo.h
diff --git a/Tests/RunCMake/FileSetProperties/h1.h b/Tests/RunCMake/FileSetProperties/h1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/h1.h
diff --git a/Tests/RunCMake/FileSetProperties/h2.h b/Tests/RunCMake/FileSetProperties/h2.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FileSetProperties/h2.h
diff --git a/Tests/RunCMake/File_Archive/CMP0213-NEW.cmake b/Tests/RunCMake/File_Archive/CMP0213-NEW.cmake
new file mode 100644
index 0000000..bf126fe
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-NEW.cmake
@@ -0,0 +1,10 @@
+set(OUTPUT_NAME "test.zip")
+
+cmake_policy(SET CMP0213 NEW)
+
+set(ARCHIVE_FORMAT zip)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/File_Archive/CMP0213-OLD-fails-result.txt
diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-stderr.txt b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-stderr.txt
new file mode 100644
index 0000000..1976196
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^
+]*
+CMake Error at roundtrip\.cmake:[0-9]+ \(file\):
+ file failed to compress:
diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD-fails.cmake b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails.cmake
new file mode 100644
index 0000000..bf5dafa
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails.cmake
@@ -0,0 +1,11 @@
+set(OUTPUT_NAME "bad.zip")
+
+cmake_policy(SET CMP0213 OLD)
+
+set(ARCHIVE_FORMAT zip)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD.cmake b/Tests/RunCMake/File_Archive/CMP0213-OLD.cmake
new file mode 100644
index 0000000..6829cf1
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-OLD.cmake
@@ -0,0 +1,10 @@
+set(OUTPUT_NAME "test.zip")
+
+cmake_policy(SET CMP0213 OLD)
+
+set(ARCHIVE_FORMAT zip)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/File_Archive/CMP0213-WARN-fails-result.txt
diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-stderr.txt b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-stderr.txt
new file mode 100644
index 0000000..1976196
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^
+]*
+CMake Error at roundtrip\.cmake:[0-9]+ \(file\):
+ file failed to compress:
diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN-fails.cmake b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails.cmake
new file mode 100644
index 0000000..30b2260
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails.cmake
@@ -0,0 +1,11 @@
+set(OUTPUT_NAME "bad.zip")
+
+# No need to set CMP0213 - WARN is default
+
+set(ARCHIVE_FORMAT zip)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN.cmake b/Tests/RunCMake/File_Archive/CMP0213-WARN.cmake
new file mode 100644
index 0000000..795c980
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/CMP0213-WARN.cmake
@@ -0,0 +1,10 @@
+set(OUTPUT_NAME "test.zip")
+
+# No need to set CMP0213 - WARN is default
+
+set(ARCHIVE_FORMAT zip)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
index a49c7f0..63071cb 100644
--- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
@@ -30,6 +30,41 @@
run_cmake(threads-xz)
run_cmake(threads-zstd)
+# Encoding tests. These rely on UTF-8 encoding of our test sources.
+if(NOT DEFINED CMake_TEST_LOCALE_CHARSET)
+ cmake_host_system_information(RESULT CMake_TEST_LOCALE_CHARSET QUERY LOCALE_CHARSET)
+ message(STATUS "Detected LOCALE_CHARSET '${CMake_TEST_LOCALE_CHARSET}'")
+endif()
+
+if(CMake_TEST_LOCALE_CHARSET STREQUAL "UTF-8")
+ if(CMAKE_HOST_WIN32)
+ # The OEM encoding cannot represent our UTF-8 test paths.
+ run_cmake(encoding-oem-gnutar-fails)
+ run_cmake(encoding-oem-zip-fails)
+ run_cmake(CMP0213-OLD-fails)
+ run_cmake(CMP0213-WARN-fails)
+ else()
+ run_cmake(encoding-oem-gnutar)
+ run_cmake(encoding-oem-zip)
+ run_cmake(CMP0213-OLD)
+ run_cmake(CMP0213-WARN)
+ endif()
+
+ run_cmake(CMP0213-NEW)
+
+ run_cmake(encoding-oem-7zip)
+ run_cmake(encoding-oem-pax)
+ run_cmake(encoding-oem-paxr)
+
+ run_cmake(encoding-utf-8-7zip)
+ run_cmake(encoding-utf-8-gnutar)
+ run_cmake(encoding-utf-8-pax)
+ run_cmake(encoding-utf-8-paxr)
+ run_cmake(encoding-utf-8-zip)
+else()
+ message(STATUS "encoding-* - SKIPPED due to non-UTF-8 locale")
+endif()
+
# Extracting only selected files or directories
run_cmake(zip-filtered)
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-7zip.cmake b/Tests/RunCMake/File_Archive/encoding-oem-7zip.cmake
new file mode 100644
index 0000000..f0e73d2
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-7zip.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.7z")
+
+set(ARCHIVE_FORMAT 7zip)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("377abcaf271c" LIMIT 6 HEX)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-result.txt
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-stderr.txt b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-stderr.txt
new file mode 100644
index 0000000..1976196
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^
+]*
+CMake Error at roundtrip\.cmake:[0-9]+ \(file\):
+ file failed to compress:
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails.cmake b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails.cmake
new file mode 100644
index 0000000..63508be
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "bad.tar")
+
+set(ARCHIVE_FORMAT gnutar)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar.cmake b/Tests/RunCMake/File_Archive/encoding-oem-gnutar.cmake
new file mode 100644
index 0000000..3f67fef
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.tar")
+
+set(ARCHIVE_FORMAT gnutar)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-pax.cmake b/Tests/RunCMake/File_Archive/encoding-oem-pax.cmake
new file mode 100644
index 0000000..ade4a86
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-pax.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.tar")
+
+set(ARCHIVE_FORMAT pax)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-paxr.cmake b/Tests/RunCMake/File_Archive/encoding-oem-paxr.cmake
new file mode 100644
index 0000000..010e10f
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-paxr.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.tar")
+
+set(ARCHIVE_FORMAT paxr)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/File_Archive/encoding-oem-zip-fails-result.txt
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-stderr.txt b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-stderr.txt
new file mode 100644
index 0000000..1976196
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^
+]*
+CMake Error at roundtrip\.cmake:[0-9]+ \(file\):
+ file failed to compress:
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip-fails.cmake b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails.cmake
new file mode 100644
index 0000000..fd48639
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "bad.zip")
+
+set(ARCHIVE_FORMAT zip)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip.cmake b/Tests/RunCMake/File_Archive/encoding-oem-zip.cmake
new file mode 100644
index 0000000..3e1bc3d
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-oem-zip.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.zip")
+
+set(ARCHIVE_FORMAT zip)
+set(ENCODING OEM)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-7zip.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-7zip.cmake
new file mode 100644
index 0000000..8fba09f
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-utf-8-7zip.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.7z")
+
+set(ARCHIVE_FORMAT 7zip)
+set(ENCODING UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("377abcaf271c" LIMIT 6 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-gnutar.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-gnutar.cmake
new file mode 100644
index 0000000..2a25ffc
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-utf-8-gnutar.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.tar")
+
+set(ARCHIVE_FORMAT gnutar)
+set(ENCODING UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-pax.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-pax.cmake
new file mode 100644
index 0000000..7c813e1
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-utf-8-pax.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.tar")
+
+set(ARCHIVE_FORMAT pax)
+set(ENCODING UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-paxr.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-paxr.cmake
new file mode 100644
index 0000000..26ff3cd
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-utf-8-paxr.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.tar")
+
+set(ARCHIVE_FORMAT paxr)
+set(ENCODING UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)
diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-zip.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-zip.cmake
new file mode 100644
index 0000000..b71cc41
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/encoding-utf-8-zip.cmake
@@ -0,0 +1,9 @@
+set(OUTPUT_NAME "test.zip")
+
+set(ARCHIVE_FORMAT zip)
+set(ENCODING UTF-8)
+include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)
diff --git a/Tests/RunCMake/File_Archive/roundtrip.cmake b/Tests/RunCMake/File_Archive/roundtrip.cmake
index a204893..12488d2 100644
--- a/Tests/RunCMake/File_Archive/roundtrip.cmake
+++ b/Tests/RunCMake/File_Archive/roundtrip.cmake
@@ -20,6 +20,7 @@
"d_4/f1.txt"
"d-4/f1.txt"
"My Special Directory/f1.txt"
+ ${COMPRESSION_ADDITIONAL_FILE_NAMES}
)
foreach(file ${CHECK_FILES})
@@ -41,16 +42,23 @@
file(MAKE_DIRECTORY ${FULL_DECOMPRESS_DIR})
endif()
+set(ENCODING_OPTIONS "")
+if (ENCODING)
+ set(ENCODING_OPTIONS ENCODING "${ENCODING}")
+endif()
+
file(ARCHIVE_CREATE
OUTPUT ${FULL_OUTPUT_NAME}
FORMAT "${ARCHIVE_FORMAT}"
COMPRESSION "${COMPRESSION_TYPE}"
WORKING_DIRECTORY "${WORKING_DIRECTORY}"
+ ${ENCODING_OPTIONS}
VERBOSE
PATHS ${FULL_COMPRESS_DIR})
file(ARCHIVE_EXTRACT
INPUT ${FULL_OUTPUT_NAME}
+ ${ENCODING_OPTIONS}
${DECOMPRESSION_OPTIONS}
DESTINATION ${FULL_DECOMPRESS_DIR}
VERBOSE)
@@ -64,18 +72,25 @@
set(output ${FULL_DECOMPRESS_DIR}/${CUSTOM_OUTPUT_DIRECTORY}/${COMPRESS_DIR}/${file})
if(NOT EXISTS ${input})
- message(SEND_ERROR "Cannot find input file ${input}")
+ message(SEND_ERROR "Cannot find input file:\n \"${output}\"")
endif()
if(NOT EXISTS ${output})
- message(SEND_ERROR "Cannot find output file ${output}")
+ message(SEND_ERROR "Cannot find output file:\n \"${output}\"")
endif()
file(MD5 ${input} input_md5)
file(MD5 ${output} output_md5)
if(NOT input_md5 STREQUAL output_md5)
- message(SEND_ERROR "Files \"${input}\" and \"${output}\" are different")
+ message(SEND_ERROR
+ "Files:\n"
+ " \"${input}\"\n"
+ "and\n"
+ " \"${output}\"\n"
+ "are different"
+ )
+
endif()
endforeach()
@@ -83,7 +98,7 @@
set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file})
if(EXISTS ${output})
- message(SEND_ERROR "File ${output} exists but it shouldn't")
+ message(SEND_ERROR "File exists but it shouldn't:\n \"${output}\"")
endif()
endforeach()
diff --git a/Tests/RunCMake/File_Archive/utf-8-paths.cmake b/Tests/RunCMake/File_Archive/utf-8-paths.cmake
new file mode 100644
index 0000000..af85ffa
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/utf-8-paths.cmake
@@ -0,0 +1,10 @@
+list(APPEND COMPRESSION_ADDITIONAL_FILE_NAMES
+ "arabic-نَسِيج.txt"
+ "armenian-Բարեւ ձեզ.txt"
+ "chinese-质地.txt"
+ "cyrillic-привет.txt"
+ "greek-Γεια.txt"
+ "hungarian-hűtő.txt"
+ "japanese-テクスチャ.txt"
+ "korean-조직.txt"
+)
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/CMakeLists.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/CMakeLists.txt
new file mode 100644
index 0000000..f54f746
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 4.3)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/RunCMakeTest.cmake
new file mode 100644
index 0000000..9b65309
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/RunCMakeTest.cmake
@@ -0,0 +1,18 @@
+include(RunCMake)
+
+function(run_cmake_and_build name)
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}-build")
+ run_cmake_with_options(${name} -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --verbose)
+endfunction()
+
+run_cmake_and_build(all)
+run_cmake_and_build(SOURCE_FILES)
+
+run_cmake(SOURCE_FILES-noexist)
+run_cmake(SOURCE_FILES-not-in-target)
+run_cmake(SOURCE_FILES-imported)
+run_cmake(SOURCE_FILES-relative)
+
+run_cmake(invalid)
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported-result.txt
similarity index 100%
copy from Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt
copy to Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported-result.txt
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported-stderr.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported-stderr.txt
new file mode 100644
index 0000000..2060f39
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at SOURCE_FILES-imported\.cmake:[0-9]+ \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_OBJECTS:c_objs,SOURCE_FILES:[^
+]*/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty4\.c>
+
+ Cannot use SOURCE_FILES argument on imported target "c_objs"
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported.cmake
new file mode 100644
index 0000000..de82c0b
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-imported.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_library(c_objs IMPORTED OBJECT)
+
+add_custom_target(obj ALL
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty4.c>
+ VERBATIM
+ )
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist-result.txt
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist-stderr.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist-stderr.txt
new file mode 100644
index 0000000..30faeee
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at SOURCE_FILES-noexist\.cmake:[0-9]+ \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_OBJECTS:c_objs,SOURCE_FILES:[^
+]*/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty4\.c>
+
+ Source file:
+
+ [^
+]*/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty4\.c
+
+ does not exist for target "c_objs"
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist.cmake
new file mode 100644
index 0000000..9459d7c
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-noexist.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_library(c_objs OBJECT empty1.c empty2.c empty3.c)
+
+add_custom_target(obj ALL
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty4.c>
+ VERBATIM
+ )
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target-result.txt
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target-stderr.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target-stderr.txt
new file mode 100644
index 0000000..5709c82
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at SOURCE_FILES-not-in-target\.cmake:[0-9]+ \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_OBJECTS:c_objs,SOURCE_FILES:[^
+]*/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty3\.c>
+
+ Source file:
+
+ [^
+]*/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty3\.c
+
+ does not exist for target "c_objs"
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target.cmake
new file mode 100644
index 0000000..206f9f8
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-not-in-target.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+add_library(c_objs OBJECT empty1.c empty2.c)
+add_library(other OBJECT empty3.c)
+
+add_custom_target(obj ALL
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty3.c>
+ VERBATIM
+ )
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative-result.txt
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative-stderr.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative-stderr.txt
new file mode 100644
index 0000000..cdb97af
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at SOURCE_FILES-relative\.cmake:[0-9]+ \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_OBJECTS:c_objs,SOURCE_FILES:empty1\.c>
+
+ Source file:
+
+ empty1\.c
+
+ is not an absolute path
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative.cmake
new file mode 100644
index 0000000..df1127c
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-relative.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_library(c_objs OBJECT empty1.c empty2.c empty3.c)
+
+add_custom_target(obj ALL
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_OBJECTS:c_objs,SOURCE_FILES:empty1.c>
+ VERBATIM
+ )
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES.cmake
new file mode 100644
index 0000000..1727847
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES.cmake
@@ -0,0 +1,53 @@
+enable_language(C)
+
+include(common.cmake)
+
+add_library(c_objs OBJECT EXCLUDE_FROM_ALL empty1.c empty2.c empty3.c)
+
+check_target_objects(single_absolute
+ "$<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty2.c>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty2(\.c)?\.(o|obj)$]]
+ )
+check_target_objects(multi
+ "$<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty1.c;${CMAKE_CURRENT_SOURCE_DIR}/empty2.c>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty1(\.c)?\.(o|obj)$]]
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty2(\.c)?\.(o|obj)$]]
+ )
+check_target_objects(multi_reordered
+ "$<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty3.c;${CMAKE_CURRENT_SOURCE_DIR}/empty2.c>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty2(\.c)?\.(o|obj)$]]
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty3(\.c)?\.(o|obj)$]]
+ )
+check_target_objects(multi_duplicate
+ "$<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty1.c;${CMAKE_CURRENT_SOURCE_DIR}/empty3.c;${CMAKE_CURRENT_SOURCE_DIR}/empty1.c>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty1(\.c)?\.(o|obj)$]]
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty3(\.c)?\.(o|obj)$]]
+ )
+
+add_subdirectory(SOURCE_FILES_subdir)
+
+if(CMake_TEST_CUDA STREQUAL "NVIDIA")
+ enable_language(CUDA)
+
+ include(CheckIPOSupported)
+ check_ipo_supported(RESULT ipo_supported LANGUAGES CUDA)
+
+ if(ipo_supported)
+ add_library(fatbin_objs OBJECT EXCLUDE_FROM_ALL empty1.cu empty2.cu)
+ set_target_properties(fatbin_objs PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON
+ CUDA_FATBIN_COMPILATION ON
+ POSITION_INDEPENDENT_CODE ON
+ INTERPROCEDURAL_OPTIMIZATION ON
+ )
+
+ check_target_objects(fatbin_1
+ "$<TARGET_OBJECTS:fatbin_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty1.cu>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/fatbin_objs\.dir(/(\.|[a-zA-Z]+))?|/build/fatbin_objs\.build/.*)/empty1(\.cu\.o)?\.fatbin$]]
+ )
+ check_target_objects(fatbin_2
+ "$<TARGET_OBJECTS:fatbin_objs,SOURCE_FILES:${CMAKE_CURRENT_SOURCE_DIR}/empty2.cu>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/fatbin_objs\.dir(/(\.|[a-zA-Z]+))?|/build/fatbin_objs\.build/.*)/empty2(\.cu\.o)?\.fatbin$]]
+ )
+ endif()
+endif()
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES_subdir/CMakeLists.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES_subdir/CMakeLists.txt
new file mode 100644
index 0000000..208977b
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES_subdir/CMakeLists.txt
@@ -0,0 +1,4 @@
+check_target_objects(single_subdir_absolute
+ "$<TARGET_OBJECTS:c_objs,SOURCE_FILES:${CMAKE_SOURCE_DIR}/empty2.c>"
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/SOURCE_FILES-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty2(\.c)?\.(o|obj)$]]
+ )
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/all.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/all.cmake
new file mode 100644
index 0000000..15991c3
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/all.cmake
@@ -0,0 +1,12 @@
+enable_language(C)
+
+include(common.cmake)
+
+add_library(c_objs OBJECT EXCLUDE_FROM_ALL empty1.c empty2.c empty3.c)
+
+check_target_objects(all
+ $<TARGET_OBJECTS:c_objs>
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/all-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty1(\.c)?\.(o|obj)$]]
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/all-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty2(\.c)?\.(o|obj)$]]
+ [[/Tests/RunCMake/GenEx-TARGET_OBJECTS/all-build((/CMakeFiles)?/c_objs\.dir(/(\.|[a-zA-Z]+))?|/build/c_objs\.build/.*)/empty3(\.c)?\.(o|obj)$]]
+ )
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/check_target_objects.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/check_target_objects.cmake
new file mode 100644
index 0000000..62e68c7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/check_target_objects.cmake
@@ -0,0 +1,13 @@
+include("${VARS_FILE}")
+
+list(LENGTH ACTUAL al)
+list(LENGTH EXPECTED el)
+if(NOT al EQUAL el)
+ message(FATAL_ERROR "Got the wrong number of objects")
+endif()
+
+foreach(a e IN ZIP_LISTS ACTUAL EXPECTED)
+ if(NOT a MATCHES "${e}")
+ message(SEND_ERROR "Object \"${a}\" does not match expected regex \"${e}\"")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/common.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/common.cmake
new file mode 100644
index 0000000..61898b3
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/common.cmake
@@ -0,0 +1,12 @@
+function(check_target_objects name genex)
+ file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}_vars_$<CONFIG>.cmake" CONTENT "
+set(EXPECTED [==[${ARGN}]==])
+set(ACTUAL [==[${genex}]==])
+")
+ add_custom_target(${name}_check ALL
+ COMMAND ${CMAKE_COMMAND}
+ "-DVARS_FILE=${CMAKE_CURRENT_BINARY_DIR}/${name}_vars_$<CONFIG>.cmake"
+ -P "${CMAKE_SOURCE_DIR}/check_target_objects.cmake"
+ VERBATIM
+ )
+endfunction()
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty1.c b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty1.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty1.c
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty1.cu b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty1.cu
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty1.cu
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty2.c b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty2.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty2.c
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty2.cu b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty2.cu
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty2.cu
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty3.c b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty3.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/empty3.c
diff --git a/Tests/RunCMake/CommandLine/Werror_dev-result.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/Werror_dev-result.txt
copy to Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid-result.txt
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid-stderr.txt b/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid-stderr.txt
new file mode 100644
index 0000000..95cebcb
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at invalid\.cmake:[0-9]+ \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_OBJECTS:c_objs,INVALID_ARGUMENT_1,INVALID_ARGUMENT_2>
+
+ Unrecognized argument:
+
+ INVALID_ARGUMENT_1
diff --git a/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid.cmake b/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid.cmake
new file mode 100644
index 0000000..e5f1b90
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_OBJECTS/invalid.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_library(c_objs OBJECT empty1.c empty2.c empty3.c)
+
+add_custom_target(obj ALL
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_OBJECTS:c_objs,INVALID_ARGUMENT_1,INVALID_ARGUMENT_2>
+ VERBATIM
+ )
diff --git a/Tests/RunCMake/GenerateExportHeader/GEH.cmake b/Tests/RunCMake/GenerateExportHeader/GEH.cmake
index 948a799..3820dcf 100644
--- a/Tests/RunCMake/GenerateExportHeader/GEH.cmake
+++ b/Tests/RunCMake/GenerateExportHeader/GEH.cmake
@@ -1,5 +1,5 @@
# Test add_compiler_export_flags without deprecation warning.
-set(CMAKE_WARN_DEPRECATED OFF)
+cmake_diagnostic(SET CMD_DEPRECATED IGNORE)
project(GenerateExportHeader)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-flush-script-check-list.cmake.in b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-flush-script-check-list.cmake.in
index b334d2b..cfc1701 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-flush-script-check-list.cmake.in
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-flush-script-check-list.cmake.in
@@ -15,9 +15,9 @@
# uncovered by checking the name buffer flushing above.
# PRE_TEST can have a config-specific tests file, POST_BUILD never does
-set(tests_file "@CMAKE_CURRENT_BINARY_DIR@/flush_script_test[1]_tests-Debug.cmake")
+set(tests_file "@CMAKE_CURRENT_BINARY_DIR@/flush_script_test_e3b0c442_tests-Debug.cmake")
if(NOT EXISTS "${tests_file}")
- set(tests_file "@CMAKE_CURRENT_BINARY_DIR@/flush_script_test[1]_tests.cmake")
+ set(tests_file "@CMAKE_CURRENT_BINARY_DIR@/flush_script_test_e3b0c442_tests.cmake")
endif()
if(NOT EXISTS "${tests_file}")
message(FATAL_ERROR "Tests file is missing")
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt
index 3ecda70..041378e 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt
@@ -4,7 +4,7 @@
*Start +[0-9]+: skip_test\.test1
*[0-9]+/[0-9]+ +Test +#[0-9]+: skip_test\.test1 .+\*\*\*Skipped +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt
index 0eaa0c0..840c410 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt
@@ -126,7 +126,7 @@
*Start +[0-9]+: TEST:prefix/both\.case/VALUE<TYPE>!1
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:prefix/both\.case/VALUE<TYPE>!1 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt
index af9ae47..b2cd8ad 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt
@@ -126,7 +126,7 @@
*Start +[0-9]+: TEST:prefix/both\.case/VALUE<TYPE>!2
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:prefix/both\.case/VALUE<TYPE>!2 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt
index 3b3d654..4e99477 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt
@@ -16,7 +16,7 @@
*Start +[0-9]+: TEST:ns\.basic\.DISABLEDnot_really_case!3
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:ns\.basic\.DISABLEDnot_really_case!3 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt
index 37a0bcf..9aaad21 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt
@@ -40,6 +40,6 @@
*Start +[0-9]+: TEST:prefix/both\.case/VALUE<TYPE>!4
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:prefix/both\.case/VALUE<TYPE>!4 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test5-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test5-stdout.txt
index ddfc5e3..8b8864b 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test5-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test5-stdout.txt
@@ -82,6 +82,6 @@
*Start +[0-9]+: TEST:prefix/both\.case/test<TYPE>!5
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:prefix/both\.case/test<TYPE>!5 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test6-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test6-stdout.txt
index 36f8de3..08ec086 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test6-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test6-stdout.txt
@@ -40,6 +40,6 @@
*Start +[0-9]+: TEST:prefix/both\.case/VALUE<suite>!6
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:prefix/both\.case/VALUE<suite>!6 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test7-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test7-stdout.txt
index 9d46f95..7a4bf07 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test7-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test7-stdout.txt
@@ -16,6 +16,6 @@
*Start +[0-9]+: TEST:prefix/both\.case/test<suite>!7
*[0-9]+/[0-9]+ +Test +#[0-9]+: TEST:prefix/both\.case/test<suite>!7 .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of [0-9]+
+100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest.cmake b/Tests/RunCMake/GoogleTest/GoogleTest.cmake
index 792f5f7..8c33cf6 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTest.cmake
@@ -6,10 +6,11 @@
include(xcode_sign_adhoc.cmake)
add_executable(fake_gtest fake_gtest.cpp)
+add_executable(fake::gtest ALIAS fake_gtest)
xcode_sign_adhoc(fake_gtest)
gtest_discover_tests(
- fake_gtest
+ fake::gtest
TEST_PREFIX TEST:
TEST_SUFFIX !1
EXTRA_ARGS how now "\"brown\" cow"
diff --git a/Tests/RunCMake/GoogleTest/WorkDirWithSpaces-test-stdout.txt b/Tests/RunCMake/GoogleTest/WorkDirWithSpaces-test-stdout.txt
index 8849fd0..0d5ee49 100644
--- a/Tests/RunCMake/GoogleTest/WorkDirWithSpaces-test-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/WorkDirWithSpaces-test-stdout.txt
@@ -2,4 +2,4 @@
.* Start 2: WorkDirWithSpaces\.test2_discovered
.* Start 3: WorkDirWithSpaces\.test1
.* Start 4: WorkDirWithSpaces\.test2
-.*0 tests failed out of 4
+.*100% tests passed out of 4
diff --git a/Tests/RunCMake/InstallExportsAsPackageInfo/RunCMakeTest.cmake b/Tests/RunCMake/InstallExportsAsPackageInfo/RunCMakeTest.cmake
index 54f3e37..973d814 100644
--- a/Tests/RunCMake/InstallExportsAsPackageInfo/RunCMakeTest.cmake
+++ b/Tests/RunCMake/InstallExportsAsPackageInfo/RunCMakeTest.cmake
@@ -6,7 +6,7 @@
# Enable experimental feature and suppress warnings
set(RunCMake_TEST_OPTIONS
- -Wno-dev
+ -Wno-author
"-DCMAKE_EXPERIMENTAL_MAPPED_PACKAGE_INFO:STRING=ababa1b5-7099-495f-a9cd-e22d38f274f2"
)
diff --git a/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake b/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake
index b7a059b..d491b66 100644
--- a/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake
+++ b/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake
@@ -48,6 +48,7 @@
endfunction()
install_test(parallel PARALLEL ARGS "-j 4")
+install_test(parallel-no-space PARALLEL ARGS "-j4")
install_test(no-parallel ARGS "-j 4")
install_test(out-of-date-json TOUCH_CACHE PARALLEL ARGS "-j 4")
install_test(component PARALLEL ARGS "-j 4" COMPONENT "ALPHANUMERIC123")
diff --git a/Tests/RunCMake/InstallParallel/parallel-no-space-install-stdout.txt b/Tests/RunCMake/InstallParallel/parallel-no-space-install-stdout.txt
new file mode 100644
index 0000000..9c059b0
--- /dev/null
+++ b/Tests/RunCMake/InstallParallel/parallel-no-space-install-stdout.txt
@@ -0,0 +1,15 @@
+\[1\/5\] .*
+\-\- Installing:[^
+]*
+\[2\/5\] .*
+\-\- Installing:[^
+]*
+\[3\/5\] .*
+\-\- Installing:[^
+]*
+\[4\/5\] .*
+\-\- Installing:[^
+]*
+\[5\/5\] .*
+\-\- Installing:[^
+]*
diff --git a/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake b/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake
index ef6b864..1a7a9e9 100644
--- a/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake
+++ b/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake
@@ -1,7 +1,7 @@
include(RunCMake)
set(common_test_options
- -Wno-dev
+ -Wno-author
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=ca494ed3-b261-4205-a01f-603c95e4cae0"
)
diff --git a/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake b/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake
index 73061eb..4439846 100644
--- a/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake
@@ -54,7 +54,15 @@
if (ARGS_TRACE_QUERY)
set(trace_query_hook_arg 1)
endif()
- set(GET_HOOK "\\\"${CMAKE_COMMAND}\\\" -P \\\"${RunCMake_SOURCE_DIR}/hook.cmake\\\" ${static_query_hook_arg} ${trace_query_hook_arg}")
+ set(GET_HOOK
+ "\\\"${CMAKE_COMMAND}\\\""
+ "-DSTATIC_QUERY=${static_query_hook_arg}"
+ "-DTRACE_QUERY=${trace_query_hook_arg}"
+ "-DPython_EXECUTABLE=${Python_EXECUTABLE}"
+ "-DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}"
+ "-P \\\"${RunCMake_SOURCE_DIR}/hook.cmake\\\""
+ )
+ list(JOIN GET_HOOK " " GET_HOOK)
# Load query JSON and cmake (with cmake_instrumentation(...)) files
set(query ${query_dir}/${test}.json.in)
@@ -63,8 +71,18 @@
file(MAKE_DIRECTORY ${v1}/query)
configure_file(${query} ${v1}/query/${test}.json)
else ()
- if (NOT EXISTS ${cmake_file} AND NOT EXISTS ${cmake_file}.in)
- set(cmake_file ${query_dir}/default.cmake)
+ if (NOT EXISTS ${cmake_file})
+ if (EXISTS ${cmake_file}.in)
+ cmake_path(GET cmake_file FILENAME cmake_filename)
+ configure_file(
+ "${cmake_file}.in"
+ "${RunCMake_TEST_BINARY_DIR}/${cmake_filename}"
+ @ONLY
+ )
+ set(cmake_file "${RunCMake_TEST_BINARY_DIR}/${cmake_filename}")
+ else ()
+ set(cmake_file ${query_dir}/default.cmake)
+ endif()
endif()
list(APPEND ARGS_CONFIGURE_ARG "-DINSTRUMENT_COMMAND_FILE=${cmake_file}")
endif()
@@ -104,12 +122,7 @@
"${RunCMake_TEST_BINARY_DIR}/CMakePresets.json"
@ONLY
)
- configure_file(
- "${cmake_file}.in"
- "${RunCMake_TEST_BINARY_DIR}/cmake-command-workflow.cmake"
- @ONLY
- )
- foreach(f IN ITEMS CMakeLists.txt main.cxx lib.cxx lib.h shell_redirect.txt)
+ foreach(f IN ITEMS CMakeLists.txt main.c lib.c lib.h shell_redirect.txt)
configure_file(
"${RunCMake_TEST_SOURCE_DIR}/${f}"
"${RunCMake_TEST_BINARY_DIR}/${f}"
diff --git a/Tests/RunCMake/Instrumentation/check-data-dir.cmake b/Tests/RunCMake/Instrumentation/check-data-dir.cmake
index 72b0f1f..bb3f4ec 100644
--- a/Tests/RunCMake/Instrumentation/check-data-dir.cmake
+++ b/Tests/RunCMake/Instrumentation/check-data-dir.cmake
@@ -39,18 +39,18 @@
string(JSON source GET "${contents}" source)
string(JSON language GET "${contents}" language)
string(JSON result GET "${contents}" result)
- if (NOT language MATCHES "C\\+\\+")
- json_error("${snippet}" "Expected C++ compile language")
+ if (NOT language STREQUAL "C")
+ json_error("${snippet}" "Expected C compile language")
endif()
- if (NOT source MATCHES "${target}.cxx$")
+ if (NOT source MATCHES "${target}.c$")
json_error("${snippet}" "Unexpected source file")
endif()
if (ARGS_FAIL)
- if (source MATCHES "dummy.cxx" AND result EQUAL 0)
+ if (source MATCHES "dummy.c" AND result EQUAL 0)
json_error("${snippet}"
"Expected nonzero exit code for compile command, got: ${result}"
)
- elseif (NOT source MATCHES "dummy.cxx" AND NOT result EQUAL 0)
+ elseif (NOT source MATCHES "dummy.c" AND NOT result EQUAL 0)
json_error("${snippet}"
"Expected zero exit code for compile command, got: ${result}"
)
diff --git a/Tests/RunCMake/Instrumentation/cmake-command-failures-build-stdout.txt b/Tests/RunCMake/Instrumentation/cmake-command-failures-build-stdout.txt
index 2d19ba1..5537f8f 100644
--- a/Tests/RunCMake/Instrumentation/cmake-command-failures-build-stdout.txt
+++ b/Tests/RunCMake/Instrumentation/cmake-command-failures-build-stdout.txt
@@ -1 +1 @@
-.*dummy\.cxx.*
+.*dummy\.c.*
diff --git a/Tests/RunCMake/Instrumentation/hook.cmake b/Tests/RunCMake/Instrumentation/hook.cmake
index cc04a14..412ef4a 100644
--- a/Tests/RunCMake/Instrumentation/hook.cmake
+++ b/Tests/RunCMake/Instrumentation/hook.cmake
@@ -1,18 +1,42 @@
cmake_minimum_required(VERSION 3.30)
include(${CMAKE_CURRENT_LIST_DIR}/json.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/validate_schema.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/verify-snippet.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/verify-trace.cmake)
# Test CALLBACK script. Prints output information and verifies index file
-# Called as: cmake -P hook.cmake [CheckForStaticQuery?] [CheckForTrace?] [index.json]
-set(index ${CMAKE_ARGV5})
-if (NOT ${CMAKE_ARGV3})
- set(hasStaticInfo "UNEXPECTED")
+# Called as: cmake -P -DSTATIC_QUERY=<ON|OFF> -DTRACE_QUERY=<ON|OFF> \
+# -DCMake_TEST_JSON_SCHEMA=<ON|OFF> -DPython_EXECUTABLE=<path> \
+# hook.cmake index-*.json
+
+# Get the index file as the last argument.
+math(EXPR last_arg_idx "${CMAKE_ARGC} - 1")
+set(index "${CMAKE_ARGV${last_arg_idx}}")
+if(NOT index MATCHES "index-.*\.json")
+ message(FATAL_ERROR "Received unexpected index argument: ${index}")
endif()
-if (NOT ${CMAKE_ARGV4})
- set(hasTrace "UNEXPECTED")
-endif()
+
+# Verify that we received the expected arguments.
+function(check_args vars)
+ foreach(var IN LISTS vars)
+ if (NOT DEFINED ${var})
+ message(FATAL_ERROR "Expected argument ${var}, but none given.")
+ endif()
+ endforeach()
+endfunction()
+check_args("STATIC_QUERY;TRACE_QUERY;Python_EXECUTABLE;CMake_TEST_JSON_SCHEMA")
+
+function(init_query_var input_var output_var)
+ set(${output_var})
+ if (NOT ${input_var})
+ set(${output_var} "UNEXPECTED")
+ endif()
+ return(PROPAGATE ${output_var})
+endfunction()
+init_query_var(STATIC_QUERY hasStaticInfo)
+init_query_var(TRACE_QUERY hasTrace)
+
read_json("${index}" contents)
string(JSON hook GET "${contents}" hook)
@@ -25,6 +49,17 @@
return(PROPAGATE ERROR_MESSAGE)
endfunction()
+validate_schema(
+ "${index}"
+ "${CMAKE_CURRENT_LIST_DIR}/../../../Help/manual/instrumentation/index-v1-schema.json"
+ # We expect to always generate valid index files.
+ 0
+)
+if (RunCMake_TEST_FAILED)
+ add_error("${RunCMake_TEST_FAILED}")
+ unset(RunCMake_TEST_FAILED)
+endif()
+
json_has_key("${index}" "${contents}" version)
json_has_key("${index}" "${contents}" buildDir)
json_has_key("${index}" "${contents}" dataDir)
diff --git a/Tests/RunCMake/Instrumentation/project/CMakeLists.txt b/Tests/RunCMake/Instrumentation/project/CMakeLists.txt
index 6e7f245..224f450 100644
--- a/Tests/RunCMake/Instrumentation/project/CMakeLists.txt
+++ b/Tests/RunCMake/Instrumentation/project/CMakeLists.txt
@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 4.3)
-project(instrumentation)
+project(instrumentation C)
enable_testing()
if (EXISTS ${INSTRUMENT_COMMAND_FILE})
include(${INSTRUMENT_COMMAND_FILE})
endif()
-add_executable(main main.cxx)
-add_library(lib lib.cxx)
+add_executable(main main.c)
+add_library(lib lib.c)
target_link_libraries(main lib)
add_custom_command(TARGET main POST_BUILD
COMMAND ${CMAKE_COMMAND} -E true
@@ -46,10 +46,10 @@
set_target_properties(lib PROPERTIES LABELS "label3")
if (FAIL)
- file(WRITE "${CMAKE_BINARY_DIR}/dummy.cxx"
+ file(WRITE "${CMAKE_BINARY_DIR}/dummy.c"
"#error \"something which will not compile\"\n"
)
- add_executable(dummy "${CMAKE_BINARY_DIR}/dummy.cxx")
+ add_executable(dummy "${CMAKE_BINARY_DIR}/dummy.c")
add_test(NAME dummy COMMAND ${CMAKE_COMMAND} -E false)
install(CODE "message(FATAL_ERROR \"Failed install.\")")
endif()
diff --git a/Tests/RunCMake/Instrumentation/project/lib.c b/Tests/RunCMake/Instrumentation/project/lib.c
new file mode 100644
index 0000000..abe3b78
--- /dev/null
+++ b/Tests/RunCMake/Instrumentation/project/lib.c
@@ -0,0 +1,4 @@
+int lib(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/Instrumentation/project/lib.cxx b/Tests/RunCMake/Instrumentation/project/lib.cxx
deleted file mode 100644
index c912397..0000000
--- a/Tests/RunCMake/Instrumentation/project/lib.cxx
+++ /dev/null
@@ -1,4 +0,0 @@
-int lib()
-{
- return 0;
-}
diff --git a/Tests/RunCMake/Instrumentation/project/lib.h b/Tests/RunCMake/Instrumentation/project/lib.h
index 9f73b0d..a9ec1de 100644
--- a/Tests/RunCMake/Instrumentation/project/lib.h
+++ b/Tests/RunCMake/Instrumentation/project/lib.h
@@ -1 +1 @@
-int lib();
+int lib(void);
diff --git a/Tests/RunCMake/Instrumentation/project/main.c b/Tests/RunCMake/Instrumentation/project/main.c
new file mode 100644
index 0000000..df19fd4
--- /dev/null
+++ b/Tests/RunCMake/Instrumentation/project/main.c
@@ -0,0 +1,5 @@
+#include "lib.h"
+int main(void)
+{
+ return lib();
+}
diff --git a/Tests/RunCMake/Instrumentation/project/main.cxx b/Tests/RunCMake/Instrumentation/project/main.cxx
deleted file mode 100644
index 0362522..0000000
--- a/Tests/RunCMake/Instrumentation/project/main.cxx
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "lib.h"
-int main()
-{
- return lib();
-}
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-cmake-build.cmake b/Tests/RunCMake/Instrumentation/query/cmake-command-cmake-build.cmake
deleted file mode 100644
index 1b0f5b1..0000000
--- a/Tests/RunCMake/Instrumentation/query/cmake-command-cmake-build.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-file(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/../hook.cmake" hook_path)
-cmake_instrumentation(
- API_VERSION 1
- DATA_VERSION 1
- HOOKS preBuild postBuild postCMakeBuild
- CALLBACK ${CMAKE_COMMAND} -P ${hook_path} 0 0
-)
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-cmake-build.cmake.in b/Tests/RunCMake/Instrumentation/query/cmake-command-cmake-build.cmake.in
new file mode 100644
index 0000000..f7f723a
--- /dev/null
+++ b/Tests/RunCMake/Instrumentation/query/cmake-command-cmake-build.cmake.in
@@ -0,0 +1,6 @@
+cmake_instrumentation(
+ API_VERSION 1
+ DATA_VERSION 1
+ HOOKS preBuild postBuild postCMakeBuild
+ CALLBACK @GET_HOOK@
+)
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-make-program.cmake b/Tests/RunCMake/Instrumentation/query/cmake-command-make-program.cmake
deleted file mode 100644
index a13033d..0000000
--- a/Tests/RunCMake/Instrumentation/query/cmake-command-make-program.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-file(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/../hook.cmake" hook_path)
-cmake_instrumentation(
- API_VERSION 1
- DATA_VERSION 1
- HOOKS preBuild postBuild
- CALLBACK ${CMAKE_COMMAND} -P ${hook_path} 0 0
-)
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-make-program.cmake.in b/Tests/RunCMake/Instrumentation/query/cmake-command-make-program.cmake.in
new file mode 100644
index 0000000..49d2ba6
--- /dev/null
+++ b/Tests/RunCMake/Instrumentation/query/cmake-command-make-program.cmake.in
@@ -0,0 +1,6 @@
+cmake_instrumentation(
+ API_VERSION 1
+ DATA_VERSION 1
+ HOOKS preBuild postBuild
+ CALLBACK @GET_HOOK@
+)
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-trace.cmake b/Tests/RunCMake/Instrumentation/query/cmake-command-trace.cmake
deleted file mode 100644
index 972b3a7..0000000
--- a/Tests/RunCMake/Instrumentation/query/cmake-command-trace.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-file(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/../hook.cmake" hook_path)
-cmake_instrumentation(
- API_VERSION 1
- DATA_VERSION 1
- OPTIONS trace
- HOOKS postBuild postCMakeInstall postCTest
- CALLBACK ${CMAKE_COMMAND} -P ${hook_path} 0 1
-)
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-trace.cmake.in b/Tests/RunCMake/Instrumentation/query/cmake-command-trace.cmake.in
new file mode 100644
index 0000000..9abb7b2
--- /dev/null
+++ b/Tests/RunCMake/Instrumentation/query/cmake-command-trace.cmake.in
@@ -0,0 +1,7 @@
+cmake_instrumentation(
+ API_VERSION 1
+ DATA_VERSION 1
+ OPTIONS trace
+ HOOKS postBuild postCMakeInstall postCTest
+ CALLBACK @GET_HOOK@
+)
diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-workflow.cmake.in b/Tests/RunCMake/Instrumentation/query/cmake-command-workflow.cmake.in
index 65b1f6a..9f8674d 100644
--- a/Tests/RunCMake/Instrumentation/query/cmake-command-workflow.cmake.in
+++ b/Tests/RunCMake/Instrumentation/query/cmake-command-workflow.cmake.in
@@ -2,5 +2,5 @@
API_VERSION 1
DATA_VERSION 1
HOOKS postCMakeWorkflow
- CALLBACK "@CMAKE_COMMAND@" -P "@RunCMake_TEST_SOURCE_DIR@/../hook.cmake" 0 0
+ CALLBACK @GET_HOOK@
)
diff --git a/Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW-config.txt b/Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW-config.txt
index ca1c340..cd5b09f 100644
--- a/Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW-config.txt
+++ b/Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW-config.txt
@@ -1,2 +1,2 @@
-[ ,][/-][Mm][Aa][Cc][Hh][Ii][Nn][Ee]:[A-Za-z0-9_]+[ ]|[Vv][Cc](98|7)\\\\[Bb][Ii][Nn]\\\\[Ll][Ii][Nn][Kk]\.[Ee][Xx][Ee] [^
+[ ,][/-][Mm][Aa][Cc][Hh][Ii][Nn][Ee]:[A-Za-z0-9_]+[ ]|[Vv][Cc](98|7)\\\\[Bb][Ii][Nn]\\\\[Ll][Ii][Nn][Kk]\.[Ee][Xx][Ee]"? [^
]*@[^ ]+\\\\nm
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index aef8870..8e90dc0 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -446,7 +446,7 @@
#run_cmake_configure(AutoMocExecutable)
#run_cmake_build(AutoMocExecutable debug-in-release-graph Release exe)
-# Need to test this manually because run_cmake() adds --no-warn-unused-cli
+# Need to test this manually because run_cmake() adds -Wno-unused-cli
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/NoUnusedVariables-build)
run_cmake_command(NoUnusedVariables ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR}
-G "Ninja Multi-Config"
diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-stderr.txt b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-stderr.txt
new file mode 100644
index 0000000..2194dd3
--- /dev/null
+++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0154-OLD\.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0154 will be removed from a future version
+ of CMake\.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances\. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ParseImplicitData/windows_x86_64-C-MSVC-19.50.35724.0.input b/Tests/RunCMake/ParseImplicitData/windows_x86_64-C-MSVC-19.50.35724.0.input
new file mode 100644
index 0000000..f79c6a3
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitData/windows_x86_64-C-MSVC-19.50.35724.0.input
@@ -0,0 +1,19 @@
+CMAKE_LANG=C
+CMAKE_LINKER=C:/Program Files/Microsoft Visual Studio/18/Professional/VC/Tools/MSVC/14.50.35717/bin/Hostx64/x64/link.exe
+CMAKE_C_COMPILER_ABI=
+CMAKE_C_COMPILER_AR=
+CMAKE_C_COMPILER_ARCHITECTURE_ID=x64
+CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=
+CMAKE_C_COMPILER_ID=MSVC
+CMAKE_C_COMPILER_LAUNCHER=
+CMAKE_C_COMPILER_LOADED=1
+CMAKE_C_COMPILER_RANLIB=
+CMAKE_C_COMPILER_TARGET=
+CMAKE_C_COMPILER_VERSION=19.50.35724.0
+CMAKE_C_COMPILER_VERSION_INTERNAL=
+CMAKE_HOST_SYSTEM_NAME=Windows
+Change Dir: 'C:/DoesNotExist/Temp/CMakeFiles/CMakeTmp'
+
+Run Build Command(s): C:/DoesNotExist/ninja/bin/ninja.exe -v cmTC_42252
+[1/2] "C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Tools\MSVC\14.50.35717\bin\Hostx64\x64\cl.exe" /nologo -D_MBCS /DWIN32 /D_WINDOWS /W3 /MDd /Zi /Ob0 /Od /RTC1 /showIncludes /FoCMakeFiles\cmTC_42252.dir\CMakeCCompilerABI.c.obj /FdCMakeFiles\cmTC_42252.dir\ /FS -c "C:\DoesNotExist\CMake\Modules\CMakeCCompilerABI.c"
+[2/2] C:\WINDOWS\system32\cmd.exe /C "cd . && "C:\DoesNotExist\CMake\build\bin\cmake.exe" -E vs_link_exe --msvc-ver=1950 --intdir=CMakeFiles\cmTC_42252.dir --rc="C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\rc.exe" --mt="C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\mt.exe" --manifests -- "C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Tools\MSVC\14.50.35717\bin\Hostx64\x64\link.exe" /nologo CMakeFiles\cmTC_42252.dir\CMakeCCompilerABI.c.obj /out:cmTC_42252.exe /implib:cmTC_42252.lib /pdb:cmTC_42252.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
diff --git a/Tests/RunCMake/ParseImplicitData/windows_x86_64-CXX-MSVC-19.50.35724.0.input b/Tests/RunCMake/ParseImplicitData/windows_x86_64-CXX-MSVC-19.50.35724.0.input
new file mode 100644
index 0000000..4e2983a
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitData/windows_x86_64-CXX-MSVC-19.50.35724.0.input
@@ -0,0 +1,19 @@
+CMAKE_LANG=CXX
+CMAKE_LINKER=C:/Program Files/Microsoft Visual Studio/18/Professional/VC/Tools/MSVC/14.50.35717/bin/Hostx64/x64/link.exe
+CMAKE_CXX_COMPILER_ABI=
+CMAKE_CXX_COMPILER_AR=
+CMAKE_CXX_COMPILER_ARCHITECTURE_ID=x64
+CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=
+CMAKE_CXX_COMPILER_ID=MSVC
+CMAKE_CXX_COMPILER_LAUNCHER=
+CMAKE_CXX_COMPILER_LOADED=1
+CMAKE_CXX_COMPILER_RANLIB=
+CMAKE_CXX_COMPILER_TARGET=
+CMAKE_CXX_COMPILER_VERSION=19.50.35724.0
+CMAKE_CXX_COMPILER_VERSION_INTERNAL=
+CMAKE_HOST_SYSTEM_NAME=Windows
+Change Dir: 'C:/DoesNotExist/Temp/CMakeFiles/CMakeTmp'
+
+Run Build Command(s): C:/DoesNotExist/ninja/bin/ninja.exe -v cmTC_6fe1d
+[1/2] "C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Tools\MSVC\14.50.35717\bin\Hostx64\x64\cl.exe" /nologo /TP -D_MBCS /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 /showIncludes /FoCMakeFiles\cmTC_6fe1d.dir\CMakeCXXCompilerABI.cpp.obj /FdCMakeFiles\cmTC_6fe1d.dir\ /FS -c "C:\DoesNotExist\CMake\Modules\CMakeCXXCompilerABI.cpp"
+[2/2] C:\WINDOWS\system32\cmd.exe /C "cd . && "C:\DoesNotExist\CMake\build\bin\cmake.exe" -E vs_link_exe --msvc-ver=1950 --intdir=CMakeFiles\cmTC_6fe1d.dir --rc="C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\rc.exe" --mt="C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\mt.exe" --manifests -- "C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Tools\MSVC\14.50.35717\bin\Hostx64\x64\link.exe" /nologo CMakeFiles\cmTC_6fe1d.dir\CMakeCXXCompilerABI.cpp.obj /out:cmTC_6fe1d.exe /implib:cmTC_6fe1d.lib /pdb:cmTC_6fe1d.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
index b887e77..5fd0e92 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
@@ -62,6 +62,7 @@
sunos5.11_i386-C-GNU-5.5.0 sunos5.11_i386-CXX-GNU-5.5.0 sunos5.11_i386-Fortran-GNU-5.5.0
windows_x86_64-C-MSVC-19.36.32543.0 windows_x86_64-CXX-MSVC-19.36.32543.0
windows_x86_64-C-MSVC-19.38.33130.0-VS windows_x86_64-CXX-MSVC-19.38.33130.0-VS
+ windows_x86_64-C-MSVC-19.50.35724.0 windows_x86_64-CXX-MSVC-19.50.35724.0
windows_x86_64-C-Clang-17.0.1-MSVC windows_x86_64-CXX-Clang-17.0.1-MSVC windows_x86_64-Fortran-LLVMFlang-17.0.1-MSVC
windows_x86_64-Fortran-LLVMFlang-18.0.0-MSVC
windows_x86_64-C-Intel-2021.9.0.20230302 windows_x86_64-CXX-Intel-2021.9.0.20230302 windows_x86_64-Fortran-Intel-2021.9.0.20230302
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/windows_x86_64-C-MSVC-19.50.35724.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/windows_x86_64-C-MSVC-19.50.35724.0.output
new file mode 100644
index 0000000..86d56a8
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/windows_x86_64-C-MSVC-19.50.35724.0.output
@@ -0,0 +1,3 @@
+libs=
+dirs=
+linker_tool=C:/Program Files/Microsoft Visual Studio/18/Professional/VC/Tools/MSVC/14\.50\.35717/bin/Hostx64/x64/link\.exe
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/windows_x86_64-CXX-MSVC-19.50.35724.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/windows_x86_64-CXX-MSVC-19.50.35724.0.output
new file mode 100644
index 0000000..86d56a8
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/windows_x86_64-CXX-MSVC-19.50.35724.0.output
@@ -0,0 +1,3 @@
+libs=
+dirs=
+linker_tool=C:/Program Files/Microsoft Visual Studio/18/Professional/VC/Tools/MSVC/14\.50\.35717/bin/Hostx64/x64/link\.exe
diff --git a/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt b/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt
index 1fe985d..3a74173 100644
--- a/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt
+++ b/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt
@@ -1,4 +1,4 @@
CMake Error at MinVersionLargerThanMax\.cmake:[0-9]+ \(cmake_policy\):
- Policy VERSION range "3\.12\.\.\.3\.8" specifies a larger minimum than maximum\.
+ Policy VERSION range "3\.12\.\.\.3\.8" specifies a later minimum than maximum\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/PrecompileHeaders/DisabledPchEnv-stdout.txt b/Tests/RunCMake/PrecompileHeaders/DisabledPchEnv-stdout.txt
new file mode 100644
index 0000000..58d0988
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/DisabledPchEnv-stdout.txt
@@ -0,0 +1,2 @@
+-- ENV{CMAKE_DISABLE_PRECOMPILE_HEADERS}='ON'
+-- CMAKE_DISABLE_PRECOMPILE_HEADERS='ON'
diff --git a/Tests/RunCMake/PrecompileHeaders/DisabledPchEnv.cmake b/Tests/RunCMake/PrecompileHeaders/DisabledPchEnv.cmake
new file mode 100644
index 0000000..fa277aa
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/DisabledPchEnv.cmake
@@ -0,0 +1,2 @@
+message(STATUS "ENV{CMAKE_DISABLE_PRECOMPILE_HEADERS}='$ENV{CMAKE_DISABLE_PRECOMPILE_HEADERS}'")
+message(STATUS "CMAKE_DISABLE_PRECOMPILE_HEADERS='${CMAKE_DISABLE_PRECOMPILE_HEADERS}'")
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index 58c45f5..d4af640 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -9,6 +9,11 @@
endfunction()
run_cmake(DisabledPch)
+block()
+ set(ENV{CMAKE_DISABLE_PRECOMPILE_HEADERS} "ON")
+ run_cmake(DisabledPchEnv)
+ unset(ENV{CMAKE_DISABLE_PRECOMPILE_HEADERS})
+endblock()
run_cmake(PchDebugGenex)
if (RunCMake_GENERATOR MATCHES "(Ninja|Makefiles|Visual Studio)")
run_cmake(PchDebugGenexShort)
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index e3409b8..688338c 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -134,7 +134,7 @@
endif()
list(APPEND RunCMake_TEST_COMMAND
-DRunCMake_TEST=${test}
- --no-warn-unused-cli
+ -Wno-unused-cli
)
else()
set(RunCMake_TEST_OPTIONS "")
diff --git a/Tests/RunCMake/Rust/Editions-build-stdout.txt b/Tests/RunCMake/Rust/Editions-build-stdout.txt
new file mode 100644
index 0000000..21786cd
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions-build-stdout.txt
@@ -0,0 +1,5 @@
+\[1/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[2/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[3/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[4/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[5/5\] Linking Rust executable (Debug[\\/])?Editions
diff --git a/Tests/RunCMake/Rust/Editions-stderr.txt b/Tests/RunCMake/Rust/Editions-stderr.txt
new file mode 100644
index 0000000..c048dd6
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Warning \(dev\) at Editions\.cmake:[0-9]+ \(enable_language\):
+ CMake's support for the Rust programming language is experimental\. It is
+ meant only for experimentation and feedback to CMake developers\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/Rust/Editions-stdout.txt b/Tests/RunCMake/Rust/Editions-stdout.txt
new file mode 100644
index 0000000..a5017df
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions-stdout.txt
@@ -0,0 +1,3 @@
+-- Configuring done \([.0-9]+s\)
+-- Generating done \([.0-9]+s\)
+-- Build files have been written to: .*[\\/]Editions-build
diff --git a/Tests/RunCMake/Rust/Editions.cmake b/Tests/RunCMake/Rust/Editions.cmake
new file mode 100644
index 0000000..0520e06
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions.cmake
@@ -0,0 +1,32 @@
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
+enable_language(Rust)
+
+# No Edition set, rustc defaults to 2015.
+add_library(Edition.2015 OBJECT edition_2015.rs)
+set_target_properties(Edition.2015 PROPERTIES Rust_EDITION 2015)
+
+# Explicitly set edition on target, without default value from variable.
+add_library(Edition.2018 OBJECT edition_2018.rs)
+set_target_properties(Edition.2018 PROPERTIES Rust_EDITION 2018)
+
+# Implicitly set edition on target from variable
+set(CMAKE_Rust_EDITION 2021)
+add_library(Edition.2021 OBJECT edition_2021.rs)
+
+# Explicitly override the edition.
+add_library(Edition.2024 OBJECT edition_2024.rs)
+set_target_properties(Edition.2024 PROPERTIES Rust_EDITION 2024)
+
+# Rust guarantees that we can link multiple crates with different editions
+# together. We specify explicitly the edition to make sure CMake properly pass
+# the edition in the linking step too.
+unset(CMAKE_Rust_EDITION)
+add_executable(Editions editions.rs)
+set_target_properties(Editions PROPERTIES Rust_EDITION 2018)
+target_link_libraries(
+ Editions PRIVATE
+ Edition.2015
+ Edition.2018
+ Edition.2021
+ Edition.2024
+)
diff --git a/Tests/RunCMake/Rust/Enable.cmake b/Tests/RunCMake/Rust/Enable.cmake
index 89d9c54..ec06ab6 100644
--- a/Tests/RunCMake/Rust/Enable.cmake
+++ b/Tests/RunCMake/Rust/Enable.cmake
@@ -1,3 +1,3 @@
-set(CMAKE_EXPERIMENTAL_RUST "3cc9b32c-47d3-4056-8953-d74e69fc0d6c")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
enable_language(Rust)
message(STATUS "CMAKE_Rust_COMPILER='${CMAKE_Rust_COMPILER}'")
diff --git a/Tests/RunCMake/Rust/RunCMakeTest.cmake b/Tests/RunCMake/Rust/RunCMakeTest.cmake
index 5178b4f..c3d0207 100644
--- a/Tests/RunCMake/Rust/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Rust/RunCMakeTest.cmake
@@ -2,3 +2,10 @@
run_cmake(Enable)
run_cmake(EnableExperimental)
+
+block()
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Editions-build)
+ run_cmake(Editions)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(Editions-build ${CMAKE_COMMAND} --build . --config Debug)
+endblock()
diff --git a/Tests/RunCMake/Rust/edition_2015.rs b/Tests/RunCMake/Rust/edition_2015.rs
new file mode 100644
index 0000000..3c85b92
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2015.rs
@@ -0,0 +1,2 @@
+// dyn is as an identifier is only allowed in Rust 2015
+pub fn dyn() {}
diff --git a/Tests/RunCMake/Rust/edition_2018.rs b/Tests/RunCMake/Rust/edition_2018.rs
new file mode 100644
index 0000000..2e68a3a
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2018.rs
@@ -0,0 +1,18 @@
+#![allow(rust_2021_compatibility)]
+
+pub trait Foo {}
+
+struct FooA {}
+impl Foo for FooA {}
+
+struct FooB {}
+impl Foo for FooB {}
+
+// dyn keyword is available in 2018+
+pub fn make_foo(value: i32) -> Box<dyn Foo> {
+ match value {
+ // Unsupported in 2021+, should be 0..=42
+ 0...42 => Box::new(FooA{}),
+ _ => Box::new(FooB{}),
+ }
+}
diff --git a/Tests/RunCMake/Rust/edition_2021.rs b/Tests/RunCMake/Rust/edition_2021.rs
new file mode 100644
index 0000000..ad113c7
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2021.rs
@@ -0,0 +1,5 @@
+// gen is becoming a keyword in 2024
+pub fn gen() -> i32 {
+ // This does not compile before Rust 2021
+ [1, 2, 3].into_iter().reduce(|acc, n| acc + n).unwrap_or(0)
+}
diff --git a/Tests/RunCMake/Rust/edition_2024.rs b/Tests/RunCMake/Rust/edition_2024.rs
new file mode 100644
index 0000000..4ba8093
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2024.rs
@@ -0,0 +1,8 @@
+pub fn add_options(a: Option<i32>, b: Option<i32>) -> Option<i32> {
+ // let chains only allowed in Rust 2024
+ if let Some(a) = a && let Some(b) = b {
+ Some(a + b)
+ } else {
+ None
+ }
+}
diff --git a/Tests/RunCMake/Rust/editions.rs b/Tests/RunCMake/Rust/editions.rs
new file mode 100644
index 0000000..01aaa74
--- /dev/null
+++ b/Tests/RunCMake/Rust/editions.rs
@@ -0,0 +1,12 @@
+
+use edition_2015;
+use edition_2018;
+use edition_2021;
+use edition_2024;
+
+fn main() {
+ edition_2015::r#dyn();
+ let _ = edition_2018::make_foo(1337);
+ let _ = edition_2021::r#gen();
+ let _ = edition_2024::add_options(None, None);
+}
diff --git a/Tests/RunCMake/Swift/CMP0157-OLD-build-stdout.txt b/Tests/RunCMake/Swift/CMP0157-OLD-build-stdout.txt
index 507fb5c..b392ea8 100644
--- a/Tests/RunCMake/Swift/CMP0157-OLD-build-stdout.txt
+++ b/Tests/RunCMake/Swift/CMP0157-OLD-build-stdout.txt
@@ -1 +1,2 @@
-swiftc(\.exe)? .* -output-file-map CMakeFiles(/|\\)greetings_default\.dir(/|\\)(Debug)?(/|\\)output-file-map\.json .*
+swiftc(\.exe)?"? [^
+]* -output-file-map CMakeFiles(/|\\)greetings_default\.dir(/|\\)(Debug)?(/|\\)output-file-map\.json .*
diff --git a/Tests/RunCMake/Swift/CMP0195-NEW-build-stdout.txt b/Tests/RunCMake/Swift/CMP0195-NEW-build-stdout.txt
index f09d187..1b1f4f1 100644
--- a/Tests/RunCMake/Swift/CMP0195-NEW-build-stdout.txt
+++ b/Tests/RunCMake/Swift/CMP0195-NEW-build-stdout.txt
@@ -1 +1,2 @@
-swiftc(\.exe)? .* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule(/|\\)[-_a-z0-9]+\.swiftmodule -module-name El
+swiftc(\.exe)?"? [^
+]* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule(/|\\)[-_a-z0-9]+\.swiftmodule -module-name El
diff --git a/Tests/RunCMake/Swift/CMP0195-OLD-build-stdout.txt b/Tests/RunCMake/Swift/CMP0195-OLD-build-stdout.txt
index 0be100d..ff096b8 100644
--- a/Tests/RunCMake/Swift/CMP0195-OLD-build-stdout.txt
+++ b/Tests/RunCMake/Swift/CMP0195-OLD-build-stdout.txt
@@ -1 +1,2 @@
-swiftc(\.exe)? .* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule -module-name El
+swiftc(\.exe)?"? [^
+]* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule -module-name El
diff --git a/Tests/RunCMake/Swift/ForceResponseFile-check-stdout.txt b/Tests/RunCMake/Swift/ForceResponseFile-check-stdout.txt
index d687c36..6f3edf3 100644
--- a/Tests/RunCMake/Swift/ForceResponseFile-check-stdout.txt
+++ b/Tests/RunCMake/Swift/ForceResponseFile-check-stdout.txt
@@ -1,2 +1,2 @@
-swiftc(\.exe)? -j [0-9]+ -num-threads [0-9]+ -c @CMakeFiles(/|\\)L\.dir(/|\\)(Debug(/|\\))?L\.o(bj)?\.swift\.rsp
-.*swiftc(\.exe)? -emit-library -static -o (Debug(/|\\))?(libL\.a|L\.lib) @CMakeFiles(/|\\)L\.(Debug\.)?rsp
+swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c @CMakeFiles(/|\\)L\.dir(/|\\)(Debug(/|\\))?L\.o(bj)?\.swift\.rsp
+.*swiftc(\.exe)?"? -emit-library -static -o (Debug(/|\\))?(libL\.a|L\.lib) @CMakeFiles(/|\\)L\.(Debug\.)?rsp
diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt
index 7ba5345..4d5c5d5 100644
--- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt
+++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt
@@ -1,20 +1,20 @@
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule[^
]* -module-name StaticLibrary [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule[^
]* -module-name DynamicLibrary [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -emit-library [^
]* -Xlinker -install_name -Xlinker @rpath/libDynamicLibrary\.dylib -o ([A-Za-z]+/)?libDynamicLibrary\.dylib [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule[^
]* -module-name DynamicLibrary2[^
]*
-.*swiftc(\.exe)? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
+.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt
index 2f9bbbc..239164c 100644
--- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt
+++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt
@@ -1,20 +1,20 @@
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug\\|Release\\)?StaticLibrary\.swiftmodule[^
]* -module-name StaticLibrary [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)\\modules\\DynamicLibrary\.swiftmodule[^
]* -module-name DynamicLibrary [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -emit-library [^
]* -Xlinker -implib:(Debug\\|Release\\)?DynamicLibrary\.lib +-o ([A-Za-z]+/)?(Debug\\|Release\\)?DynamicLibrary\.dll [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules\\(Debug\\|Release\\)?DynamicLibrary2\.swiftmodule[^
]* -module-name DynamicLibrary2 [^
]*
-.*swiftc(\.exe)? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
+.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt
index e74fdf9..7f2a341 100644
--- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt
+++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt
@@ -1,20 +1,20 @@
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule[^
]* -module-name StaticLibrary [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule[^
]* -module-name DynamicLibrary [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -emit-library [^
]* -Xlinker -soname -Xlinker libDynamicLibrary\.so -o ([A-Za-z]+/)?libDynamicLibrary\.so [^
]*
-.*swiftc(\.exe)? [^
+.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule[^
]* -module-name DynamicLibrary2[^
]*
-.*swiftc(\.exe)? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
+.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 79b1ff8..ad6c676 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -54,6 +54,7 @@
\* CMP0204
\* CMP0209
\* CMP0210
+ \* CMP0211
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
diff --git a/Tests/RunCMake/VerifyHeaderSets/RunCMakeTest.cmake b/Tests/RunCMake/VerifyHeaderSets/RunCMakeTest.cmake
index 61e4df7..e9a5747 100644
--- a/Tests/RunCMake/VerifyHeaderSets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VerifyHeaderSets/RunCMakeTest.cmake
@@ -46,6 +46,17 @@
run_cmake_build(VerifyInterfaceHeaderSets interface list)
run_cmake_build(VerifyInterfaceHeaderSets interface skip_linting)
+if(CMake_TEST_OBJC)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_VERIFY_INTERFACE_HEADER_SETS=ON)
+ if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ run_cmake(VerifyInterfaceHeaderSetsObjC)
+ unset(RunCMake_TEST_OPTIONS)
+ run_cmake_build(VerifyInterfaceHeaderSetsObjC interface lang_test_objc)
+ run_cmake_build(VerifyInterfaceHeaderSetsObjC interface lang_test_objcxx)
+endif()
+
set(RunCMake_TEST_OPTIONS -DCMAKE_VERIFY_INTERFACE_HEADER_SETS=ON)
run_cmake(AllVerifyInterfaceHeaderSets)
unset(RunCMake_TEST_OPTIONS)
@@ -94,6 +105,17 @@
run_cmake_build(VerifyPrivateHeaderSets private list)
run_cmake_build(VerifyPrivateHeaderSets private skip_linting)
+if(CMake_TEST_OBJC)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_VERIFY_PRIVATE_HEADER_SETS=ON)
+ if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ run_cmake(VerifyPrivateHeaderSetsObjC)
+ unset(RunCMake_TEST_OPTIONS)
+ run_cmake_build(VerifyPrivateHeaderSetsObjC private lang_test_objc)
+ run_cmake_build(VerifyPrivateHeaderSetsObjC private lang_test_objcxx)
+endif()
+
set(RunCMake_TEST_OPTIONS -DCMAKE_VERIFY_PRIVATE_HEADER_SETS=ON)
run_cmake(AllVerifyPrivateHeaderSets)
unset(RunCMake_TEST_OPTIONS)
@@ -103,3 +125,21 @@
set(RunCMake_TEST_OPTIONS -DCMAKE_VERIFY_PRIVATE_HEADER_SETS=ON)
run_cmake(VerifyPrivateHeaderSetsNonexistent)
unset(RunCMake_TEST_OPTIONS)
+
+# Test that verify targets are always created even with no headers
+if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+endif()
+run_cmake(VerifyEmptyHeaderSets)
+unset(RunCMake_TEST_OPTIONS)
+
+run_cmake_build(VerifyEmptyHeaderSets interface empty_iface)
+run_cmake_build(VerifyEmptyHeaderSets private empty_priv)
+run_cmake_build(VerifyEmptyHeaderSets interface all)
+run_cmake_build(VerifyEmptyHeaderSets private all)
+
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VerifyEmptyHeaderSets-build)
+set(RunCMake_TEST_NO_CLEAN 1)
+run_cmake_command(VerifyEmptyHeaderSets-all_verify_header_sets-Debug-build
+ ${CMAKE_COMMAND} --build . --config Debug --target all_verify_header_sets
+)
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyEmptyHeaderSets.cmake b/Tests/RunCMake/VerifyHeaderSets/VerifyEmptyHeaderSets.cmake
new file mode 100644
index 0000000..d1aeaca
--- /dev/null
+++ b/Tests/RunCMake/VerifyHeaderSets/VerifyEmptyHeaderSets.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+# Target with VERIFY_INTERFACE_HEADER_SETS ON but no interface file sets
+add_library(empty_iface STATIC lib.c)
+set_property(TARGET empty_iface PROPERTY VERIFY_INTERFACE_HEADER_SETS ON)
+
+# Target with VERIFY_PRIVATE_HEADER_SETS ON but no private file sets
+add_library(empty_priv STATIC lib.c)
+set_property(TARGET empty_priv PROPERTY VERIFY_PRIVATE_HEADER_SETS ON)
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-private-Debug-build-result.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-private-Debug-build-result.txt
deleted file mode 100644
index d197c91..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-private-Debug-build-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-[^0]
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-private-Debug-build-stderr.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-private-Debug-build-stderr.txt
deleted file mode 100644
index 8d98f9d..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSets-private-Debug-build-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-.*
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSetsObjC.cmake b/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSetsObjC.cmake
new file mode 100644
index 0000000..4830d24
--- /dev/null
+++ b/Tests/RunCMake/VerifyHeaderSets/VerifyInterfaceHeaderSetsObjC.cmake
@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0209 NEW)
+
+enable_language(C CXX OBJC OBJCXX)
+
+add_library(lang_test_objc STATIC lib.m)
+target_sources(lang_test_objc INTERFACE FILE_SET HEADERS FILES lang_test.h)
+target_compile_definitions(lang_test_objc INTERFACE EXPECT_OBJC)
+
+# OBJC + OBJCXX sources -> lattice promotes to OBJCXX for unlanguaged headers
+add_library(lang_test_objcxx STATIC lib.m lib.mm)
+target_sources(lang_test_objcxx INTERFACE FILE_SET HEADERS FILES lang_test.h)
+target_compile_definitions(lang_test_objcxx INTERFACE EXPECT_CXX EXPECT_OBJC)
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-iface_lang_cxx-Debug-build-result.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-iface_lang_cxx-Debug-build-result.txt
deleted file mode 100644
index d197c91..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-iface_lang_cxx-Debug-build-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-[^0]
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-iface_lang_cxx-Debug-build-stderr.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-iface_lang_cxx-Debug-build-stderr.txt
deleted file mode 100644
index 8d98f9d..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-iface_lang_cxx-Debug-build-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-.*
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-interface-Debug-build-result.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-interface-Debug-build-result.txt
deleted file mode 100644
index d197c91..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-interface-Debug-build-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-[^0]
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-interface-Debug-build-stderr.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-interface-Debug-build-stderr.txt
deleted file mode 100644
index 8d98f9d..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-interface-Debug-build-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-.*
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-none-Debug-build-result.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-none-Debug-build-result.txt
deleted file mode 100644
index d197c91..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-none-Debug-build-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-[^0]
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-none-Debug-build-stderr.txt b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-none-Debug-build-stderr.txt
deleted file mode 100644
index 8d98f9d..0000000
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSets-none-Debug-build-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-.*
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSetsObjC.cmake b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSetsObjC.cmake
new file mode 100644
index 0000000..53bfce2
--- /dev/null
+++ b/Tests/RunCMake/VerifyHeaderSets/VerifyPrivateHeaderSetsObjC.cmake
@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0209 NEW)
+
+enable_language(C CXX OBJC OBJCXX)
+
+add_library(lang_test_objc STATIC lib.m)
+target_sources(lang_test_objc PRIVATE FILE_SET HEADERS FILES lang_test.h)
+target_compile_definitions(lang_test_objc PRIVATE EXPECT_OBJC)
+
+# OBJC + OBJCXX sources -> lattice promotes to OBJCXX for unlanguaged headers
+add_library(lang_test_objcxx STATIC lib.m lib.mm)
+target_sources(lang_test_objcxx PRIVATE FILE_SET HEADERS FILES lang_test.h)
+target_compile_definitions(lang_test_objcxx PRIVATE EXPECT_CXX EXPECT_OBJC)
diff --git a/Tests/RunCMake/VerifyHeaderSets/lang_test.h b/Tests/RunCMake/VerifyHeaderSets/lang_test.h
index 633a2a4..347a247 100644
--- a/Tests/RunCMake/VerifyHeaderSets/lang_test.h
+++ b/Tests/RunCMake/VerifyHeaderSets/lang_test.h
@@ -5,4 +5,11 @@
# error "__cplusplus not defined but EXPECT_CXX defined"
#endif
+#if defined(__OBJC__) && !defined(EXPECT_OBJC)
+# error "__OBJC__ defined but EXPECT_OBJC not defined"
+#endif
+#if !defined(__OBJC__) && defined(EXPECT_OBJC)
+# error "__OBJC__ not defined but EXPECT_OBJC defined"
+#endif
+
extern void lang_test_h(void);
diff --git a/Tests/RunCMake/VerifyHeaderSets/lib.m b/Tests/RunCMake/VerifyHeaderSets/lib.m
new file mode 100644
index 0000000..5952ed2
--- /dev/null
+++ b/Tests/RunCMake/VerifyHeaderSets/lib.m
@@ -0,0 +1,3 @@
+void lang_test_h(void)
+{
+}
diff --git a/Tests/RunCMake/VerifyHeaderSets/lib.mm b/Tests/RunCMake/VerifyHeaderSets/lib.mm
new file mode 100644
index 0000000..1119f87
--- /dev/null
+++ b/Tests/RunCMake/VerifyHeaderSets/lib.mm
@@ -0,0 +1,3 @@
+void lang_test_h_mm(void)
+{
+}
diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
index 803518a..89a5f51 100644
--- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
@@ -15,6 +15,14 @@
run_cmake_script(Locale)
unset(RunCMake-stdout-file)
+if(CMake_TEST_LOCALE_C_UTF8 OR CMAKE_HOST_WIN32)
+ set(RunCMake-stdout-file Locale-stdout-utf-8.txt)
+ run_cmake_command(LocaleC-UTF8 ${CMAKE_COMMAND} -E env LC_CTYPE=C ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/Locale.cmake)
+ run_cmake_command(LocaleBad-UTF8 ${CMAKE_COMMAND} -E env LC_CTYPE=Bad ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/Locale.cmake)
+ run_cmake_command(LocalePOSIX-UTF8 ${CMAKE_COMMAND} -E env LC_CTYPE=POSIX ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/Locale.cmake)
+ unset(RunCMake-stdout-file)
+endif()
+
run_cmake(UnitTest)
run_cmake(Exherbo)
run_cmake(Ubuntu)
diff --git a/Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt b/Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt
index 2d7afc0..3d0c2f7 100644
--- a/Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt
+++ b/Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt
@@ -1,56 +1,56 @@
-^CMake Error at RangeBad\.cmake:1 \(cmake_minimum_required\):
+^CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_minimum_required\):
cmake_minimum_required VERSION "3\.11\.\.\." does not have a version on both
sides of "\.\.\."\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:2 \(cmake_minimum_required\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_minimum_required\):
cmake_minimum_required VERSION "\.\.\.3\.11" does not have a version on both
sides of "\.\.\."\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:3 \(cmake_minimum_required\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_minimum_required\):
cmake_minimum_required VERSION "\.\.\." does not have a version on both sides
of "\.\.\."\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:4 \(cmake_minimum_required\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_minimum_required\):
Invalid policy max version value "4"\. A numeric
major\.minor\[\.patch\[\.tweak\]\] must be given\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:5 \(cmake_minimum_required\):
- Policy VERSION range "3\.11\.\.\.3\.10" specifies a larger minimum than maximum\.
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_minimum_required\):
+ Policy VERSION range "3\.11\.\.\.3\.10" specifies a later minimum than maximum\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:6 \(cmake_policy\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_policy\):
cmake_policy VERSION "3\.11\.\.\." does not have a version on both sides of
"\.\.\."\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:7 \(cmake_policy\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_policy\):
cmake_policy VERSION "\.\.\.3\.11" does not have a version on both sides of
"\.\.\."\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:8 \(cmake_policy\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_policy\):
cmake_policy VERSION "\.\.\." does not have a version on both sides of "\.\.\."\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:9 \(cmake_policy\):
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_policy\):
Invalid policy max version value "4"\. A numeric
major\.minor\[\.patch\[\.tweak\]\] must be given\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
+
-CMake Error at RangeBad\.cmake:10 \(cmake_policy\):
- Policy VERSION range "3\.11\.\.\.3\.10" specifies a larger minimum than maximum\.
+CMake Error at RangeBad\.cmake:[0-9]+ \(cmake_policy\):
+ Policy VERSION range "3\.11\.\.\.3\.10" specifies a later minimum than maximum\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)$
diff --git a/Tests/RunCMake/create_test_sourcelist/CMakeLists.txt b/Tests/RunCMake/create_test_sourcelist/CMakeLists.txt
new file mode 100644
index 0000000..902f0bb
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} LANGUAGES NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/create_test_sourcelist/Discovery-test-stdout.txt b/Tests/RunCMake/create_test_sourcelist/Discovery-test-stdout.txt
new file mode 100644
index 0000000..9157e8c
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/Discovery-test-stdout.txt
@@ -0,0 +1,9 @@
+Test project [^
+]*/Tests/RunCMake/create_test_sourcelist/Discovery-build
+ Start 1: case_one
+.*
+ Start 2: case_two
+.*
+ Start 3: case_three
+.*
+100% tests passed out of 3
diff --git a/Tests/RunCMake/create_test_sourcelist/Discovery.cmake b/Tests/RunCMake/create_test_sourcelist/Discovery.cmake
new file mode 100644
index 0000000..45fae1b
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/Discovery.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+enable_testing()
+
+create_test_sourcelist(DRIVER_SRCS
+ main.c
+ case_one.c
+ case_two.c
+ case_three.c
+)
+
+add_executable(test_driver ${DRIVER_SRCS})
+
+discover_tests(COMMAND test_driver
+ DISCOVERY_ARGS -N
+ DISCOVERY_MATCH ".*"
+ TEST_NAME "\\0"
+ TEST_ARGS "\\0"
+)
diff --git a/Tests/RunCMake/create_test_sourcelist/RunCMakeTest.cmake b/Tests/RunCMake/create_test_sourcelist/RunCMakeTest.cmake
new file mode 100644
index 0000000..925c58a
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/RunCMakeTest.cmake
@@ -0,0 +1,19 @@
+include(RunCMake)
+
+# Isolate our ctest runs from external environment.
+unset(ENV{CTEST_PARALLEL_LEVEL})
+unset(ENV{CTEST_OUTPUT_ON_FAILURE})
+
+if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+endif()
+
+function(run_case CASE)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${CASE}-build)
+ run_cmake(${CASE})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${CASE}-build ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${CASE}-test ${CMAKE_CTEST_COMMAND} -C Debug)
+endfunction()
+
+run_case(Discovery)
diff --git a/Tests/RunCMake/create_test_sourcelist/case_one.c b/Tests/RunCMake/create_test_sourcelist/case_one.c
new file mode 100644
index 0000000..8e84f6f
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/case_one.c
@@ -0,0 +1,5 @@
+int case_one(int argc, char** argv)
+{
+ (void)argc, (void)argv;
+ return 0;
+}
diff --git a/Tests/RunCMake/create_test_sourcelist/case_three.c b/Tests/RunCMake/create_test_sourcelist/case_three.c
new file mode 100644
index 0000000..8003555
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/case_three.c
@@ -0,0 +1,5 @@
+int case_three(int argc, char** argv)
+{
+ (void)argc, (void)argv;
+ return 0;
+}
diff --git a/Tests/RunCMake/create_test_sourcelist/case_two.c b/Tests/RunCMake/create_test_sourcelist/case_two.c
new file mode 100644
index 0000000..253a059
--- /dev/null
+++ b/Tests/RunCMake/create_test_sourcelist/case_two.c
@@ -0,0 +1,5 @@
+int case_two(int argc, char** argv)
+{
+ (void)argc, (void)argv;
+ return 0;
+}
diff --git a/Tests/RunCMake/ctest_build/BuildDirectories-check.cmake b/Tests/RunCMake/ctest_build/BuildDirectories-check.cmake
new file mode 100644
index 0000000..e704c52
--- /dev/null
+++ b/Tests/RunCMake/ctest_build/BuildDirectories-check.cmake
@@ -0,0 +1,18 @@
+file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml")
+if(build_xml_file)
+ file(READ "${build_xml_file}" build_xml LIMIT 4096)
+ if(NOT build_xml MATCHES [[<SourceDirectory>]])
+ string(REPLACE "\n" "\n " build_xml " ${build_xml}")
+ set(RunCMake_TEST_FAILED
+ "Build.xml does not have expected attribute:\n${build_xml}"
+ )
+ endif()
+ if(NOT build_xml MATCHES [[<BinaryDirectory>]])
+ string(REPLACE "\n" "\n " build_xml " ${build_xml}")
+ set(RunCMake_TEST_FAILED
+ "Build.xml does not have expected attribute:\n${build_xml}"
+ )
+ endif()
+else()
+ set(RunCMake_TEST_FAILED "Build.xml not found")
+endif()
diff --git a/Tests/RunCMake/ctest_build/BuildDirectories-result.txt b/Tests/RunCMake/ctest_build/BuildDirectories-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_build/BuildDirectories-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_build/BuildDirectories-stderr.txt b/Tests/RunCMake/ctest_build/BuildDirectories-stderr.txt
new file mode 100644
index 0000000..bbe9410
--- /dev/null
+++ b/Tests/RunCMake/ctest_build/BuildDirectories-stderr.txt
@@ -0,0 +1 @@
+^Error\(s\) when building project
diff --git a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
index f45a972..34ef64f 100644
--- a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
@@ -61,6 +61,11 @@
run_ctest(BuildCommandFailure)
unset(RunCMake_BUILD_COMMAND)
+set(RunCMake_USE_CUSTOM_BUILD_COMMAND TRUE)
+set(RunCMake_BUILD_COMMAND "${FAKE_BUILD_COMMAND_EXE}")
+run_ctest(BuildDirectories)
+unset(RunCMake_BUILD_COMMAND)
+
set(RunCMake_USE_LAUNCHERS FALSE)
set(RunCMake_BUILD_COMMAND "${COLOR_WARNING}")
run_ctest(IgnoreColor)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt
index a78dfe1..f44584a 100644
--- a/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt
+++ b/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt
@@ -3,7 +3,7 @@
Start 2: CleanupTest
2/2 Test #2: CleanupTest \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*\*\*\Not Run \(Disabled\) +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt
index f56fb5c..a88606f 100644
--- a/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt
+++ b/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt
@@ -5,7 +5,7 @@
Start 3: SuccessfulCleanupTest
3/3 Test #3: SuccessfulCleanupTest \.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt
index 28a1ff5..3cd2573 100644
--- a/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt
+++ b/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt
@@ -5,7 +5,7 @@
Start 3: SuccessfulCleanupTest
3/3 Test #3: SuccessfulCleanupTest \.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt
index 620cde7..b0b0793 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt
@@ -10,6 +10,6 @@
Start 6: two
5/5 Test #6: two +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 5
+100% tests passed out of 5
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt
index d6ab3ec..0f8917c 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt
@@ -8,6 +8,6 @@
Start 7: cleanupBar
4/4 Test #7: cleanupBar +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt
index ce9c1aa..ccc0c95 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt
@@ -4,6 +4,6 @@
Start 6: two
2/2 Test #6: two +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt
index c7c7da8..9a5ff40 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt
@@ -10,6 +10,6 @@
Start 6: two
5/5 Test #6: two +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 5
+100% tests passed out of 5
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt
index 58888a4..dbbaa2b 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt
@@ -10,6 +10,6 @@
Start 7: cleanupBar
5/5 Test #7: cleanupBar +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 5
+100% tests passed out of 5
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt
index cba4f1a..d19d832 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt
@@ -12,6 +12,6 @@
Start 7: cleanupBar
6/6 Test #7: cleanupBar +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 6
+100% tests passed out of 6
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt
index a0c8337..bd3590a 100644
--- a/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt
@@ -10,6 +10,6 @@
Start 7: cleanupBar
5/5 Test #7: cleanupBar +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 5
+100% tests passed out of 5
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/one-stdout.txt b/Tests/RunCMake/ctest_fixtures/one-stdout.txt
index a0005ba..cb06efb 100644
--- a/Tests/RunCMake/ctest_fixtures/one-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/one-stdout.txt
@@ -8,6 +8,6 @@
Start 5: cleanupFoo
4/4 Test #5: cleanupFoo +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/setupFoo-stdout.txt b/Tests/RunCMake/ctest_fixtures/setupFoo-stdout.txt
index a45b66f..14df56d 100644
--- a/Tests/RunCMake/ctest_fixtures/setupFoo-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/setupFoo-stdout.txt
@@ -2,6 +2,6 @@
Start 3: setupFoo
1/1 Test #3: setupFoo +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/three-stdout.txt b/Tests/RunCMake/ctest_fixtures/three-stdout.txt
index 2c33c6b..f125153 100644
--- a/Tests/RunCMake/ctest_fixtures/three-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/three-stdout.txt
@@ -12,6 +12,6 @@
Start 7: cleanupBar
6/6 Test #7: cleanupBar +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 6
+100% tests passed out of 6
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/two-stdout.txt b/Tests/RunCMake/ctest_fixtures/two-stdout.txt
index 4c03789..f20de15 100644
--- a/Tests/RunCMake/ctest_fixtures/two-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/two-stdout.txt
@@ -6,6 +6,6 @@
Start 7: cleanupBar
3/3 Test #7: cleanupBar +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 3
+100% tests passed out of 3
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/unused-stdout.txt b/Tests/RunCMake/ctest_fixtures/unused-stdout.txt
index c0a21b0..e714f52 100644
--- a/Tests/RunCMake/ctest_fixtures/unused-stdout.txt
+++ b/Tests/RunCMake/ctest_fixtures/unused-stdout.txt
@@ -4,6 +4,6 @@
Start 13: cleanupUnused
2/2 Test #13: cleanupUnused +.+ +Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_memcheck/DummyBC-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyBC-stdout.txt
index b37e9e8..32ef557 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyBC-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyBC-stdout.txt
@@ -1,3 +1,3 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/ctest_memcheck/DummyBCNoLogFile-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyBCNoLogFile-stdout.txt
index b37e9e8..32ef557 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyBCNoLogFile-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyBCNoLogFile-stdout.txt
@@ -1,3 +1,3 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/ctest_memcheck/DummyPurify-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyPurify-stdout.txt
index e988b8f..15373ae 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyPurify-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyPurify-stdout.txt
@@ -1,6 +1,6 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_memcheck/DummyPurifyNoLogFile-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyPurifyNoLogFile-stdout.txt
index b37e9e8..32ef557 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyPurifyNoLogFile-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyPurifyNoLogFile-stdout.txt
@@ -1,3 +1,3 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/ctest_memcheck/DummyQuiet-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyQuiet-stdout.txt
index 58f55a5..722d5ed 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyQuiet-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyQuiet-stdout.txt
@@ -1 +1 @@
-0 tests failed out of 1$
+100% tests passed out of 1$
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrind-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrind-stdout.txt
index e988b8f..15373ae 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrind-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrind-stdout.txt
@@ -1,6 +1,6 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindCustomOptions-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindCustomOptions-stdout.txt
index e988b8f..15373ae 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrindCustomOptions-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindCustomOptions-stdout.txt
@@ -1,6 +1,6 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindFailPost-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindFailPost-stdout.txt
index e988b8f..15373ae 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrindFailPost-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindFailPost-stdout.txt
@@ -1,6 +1,6 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindIgnoreMemcheck-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindIgnoreMemcheck-stdout.txt
index 9743ada..6db1106 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrindIgnoreMemcheck-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindIgnoreMemcheck-stdout.txt
@@ -1,7 +1,7 @@
2/2 Test #2: RunCMakeAgain .*
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt
index e988b8f..15373ae 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt
@@ -1,6 +1,6 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoLogFile-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoLogFile-stdout.txt
index b37e9e8..32ef557 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrindNoLogFile-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindNoLogFile-stdout.txt
@@ -1,3 +1,3 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
diff --git a/Tests/RunCMake/ctest_memcheck/DummyValgrindPrePost-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyValgrindPrePost-stdout.txt
index e988b8f..15373ae 100644
--- a/Tests/RunCMake/ctest_memcheck/DummyValgrindPrePost-stdout.txt
+++ b/Tests/RunCMake/ctest_memcheck/DummyValgrindPrePost-stdout.txt
@@ -1,6 +1,6 @@
1/1 MemCheck #1: RunCMake .+ Passed +[0-9]+\.[0-9]+ sec
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
.*
-- Processing memory checking output:
MemCheck log files can be found here:.*corresponds to test number.
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt
index 07a515b..c31f650 100644
--- a/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt
+++ b/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt
@@ -3,7 +3,7 @@
Start 2: CleanupTest
2/2 Test #2: CleanupTest \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*\*\*\Skipped +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt
index 821dfd9..53fcee4 100644
--- a/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt
+++ b/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt
@@ -5,7 +5,7 @@
Start 3: SuccessfulCleanupTest
3/3 Test #3: SuccessfulCleanupTest \.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 3
+100% tests passed out of 3
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt
index a544530..d3fa9f0 100644
--- a/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt
+++ b/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt
@@ -5,7 +5,7 @@
Start 3: SuccessfulCleanupTest
3/3 Test #3: SuccessfulCleanupTest \.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 3
+100% tests passed out of 3
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt
index d01ee3e..2352591 100644
--- a/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt
+++ b/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt
@@ -3,7 +3,7 @@
Start 2: SkipTest
2/2 Test #2: SkipTest \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*\*\*\Skipped +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
+
Total Test time \(real\) = +[0-9\.]+ sec
+
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt
index b70e11b..3bb26f4 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt
@@ -9,6 +9,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt
index 4ffa0de..a41636d 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt
@@ -9,6 +9,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadWait0-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadWait0-stdout.txt
index 07eab96..5cc84e5 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadWait0-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadWait0-stdout.txt
@@ -10,6 +10,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadWait1-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadWait1-stdout.txt
index b6015f8..d78646b 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadWait1-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadWait1-stdout.txt
@@ -10,6 +10,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/ResourceLock-stdout.txt b/Tests/RunCMake/ctest_test/ResourceLock-stdout.txt
index 9c67d6d..0e82b49 100644
--- a/Tests/RunCMake/ctest_test/ResourceLock-stdout.txt
+++ b/Tests/RunCMake/ctest_test/ResourceLock-stdout.txt
@@ -9,4 +9,4 @@
Start 5: test4
4/4 Test #5: test4 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
diff --git a/Tests/RunCMake/ctest_test/SerialOrder-stdout.txt b/Tests/RunCMake/ctest_test/SerialOrder-stdout.txt
index 81e97e0..52ff903 100644
--- a/Tests/RunCMake/ctest_test/SerialOrder-stdout.txt
+++ b/Tests/RunCMake/ctest_test/SerialOrder-stdout.txt
@@ -13,4 +13,4 @@
Start 3: test2
6/6 Test #3: test2 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 6
+100% tests passed out of 6
diff --git a/Tests/RunCMake/ctest_test/SkipReturnCode-stdout.txt b/Tests/RunCMake/ctest_test/SkipReturnCode-stdout.txt
index 9d0b06e..74b59f1 100644
--- a/Tests/RunCMake/ctest_test/SkipReturnCode-stdout.txt
+++ b/Tests/RunCMake/ctest_test/SkipReturnCode-stdout.txt
@@ -5,4 +5,4 @@
Start 2: skip
2/2 Test #2: skip \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*\*\*Skipped +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 2
+100% tests passed out of 2
diff --git a/Tests/RunCMake/ctest_test/TestEnvironment-check.cmake b/Tests/RunCMake/ctest_test/TestEnvironment-check.cmake
index 91c9731..7892454 100644
--- a/Tests/RunCMake/ctest_test/TestEnvironment-check.cmake
+++ b/Tests/RunCMake/ctest_test/TestEnvironment-check.cmake
@@ -2,7 +2,7 @@
string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}")
file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents)
-if(NOT _test_contents MATCHES "<Value>ENV1=env1\nENV2=env2\n#CTEST_RESOURCE_GROUP_COUNT=</Value>")
+if(NOT _test_contents MATCHES "<Value>#CTEST_RESOURCE_GROUP_COUNT=\nENV1=env1\nENV2=env2</Value>")
string(APPEND RunCMake_TEST_FAILED "Could not find expected environment variables in Test.xml")
endif()
if(_test_contents MATCHES "BAD_ENVIRONMENT_VARIABLE")
diff --git a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt
index 0ad3fd1..043ccf8 100644
--- a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt
@@ -9,6 +9,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt
index 4f7329b..c9b2521 100644
--- a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt
@@ -9,6 +9,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt
index c56bed3..f5a8bf4 100644
--- a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt
@@ -9,6 +9,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestLoadWait0-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadWait0-stdout.txt
index 4521c58..a4da046 100644
--- a/Tests/RunCMake/ctest_test/TestLoadWait0-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadWait0-stdout.txt
@@ -10,6 +10,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestLoadWait1-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadWait1-stdout.txt
index c0b73ad..a8c1ac4 100644
--- a/Tests/RunCMake/ctest_test/TestLoadWait1-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadWait1-stdout.txt
@@ -10,6 +10,6 @@
]*)*
1/1 Test #1: RunCMakeVersion \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt b/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt
index 761780d..0096d19 100644
--- a/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt
@@ -5,6 +5,6 @@
Start 1: testRepeat
Test #1: testRepeat \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt b/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt
index 3cec368..472449f 100644
--- a/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt
@@ -5,6 +5,6 @@
Start 1: testRepeat
Test #1: testRepeat \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
Total Test time \(real\) = +[0-9\.]+ sec$
diff --git a/Tests/RunCMake/ctest_test/TestsFromFile-exclude-empty-stdout.txt b/Tests/RunCMake/ctest_test/TestsFromFile-exclude-empty-stdout.txt
index cb6063c..ac8562a 100644
--- a/Tests/RunCMake/ctest_test/TestsFromFile-exclude-empty-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestsFromFile-exclude-empty-stdout.txt
@@ -9,4 +9,4 @@
+Start 4: Test11
4/4 Test #4: Test11 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 4
+100% tests passed out of 4
diff --git a/Tests/RunCMake/ctest_test/TestsFromFile-exclude-stdout.txt b/Tests/RunCMake/ctest_test/TestsFromFile-exclude-stdout.txt
index 5005c80..be82138 100644
--- a/Tests/RunCMake/ctest_test/TestsFromFile-exclude-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestsFromFile-exclude-stdout.txt
@@ -7,5 +7,5 @@
+Start 4: Test11
3/3 Test #4: Test11 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 3
+100% tests passed out of 3
+
diff --git a/Tests/RunCMake/ctest_test/TestsFromFile-include-stdout.txt b/Tests/RunCMake/ctest_test/TestsFromFile-include-stdout.txt
index 4722fcb..76bcee1 100644
--- a/Tests/RunCMake/ctest_test/TestsFromFile-include-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestsFromFile-include-stdout.txt
@@ -3,5 +3,5 @@
+Start 2: Test1
1/1 Test #2: Test1 \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Passed +[0-9\.]+ sec
+
-100% tests passed, 0 tests failed out of 1
+100% tests passed out of 1
+
diff --git a/Tests/RunCMake/discover_tests/CMakeLists.txt b/Tests/RunCMake/discover_tests/CMakeLists.txt
new file mode 100644
index 0000000..902f0bb
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} LANGUAGES NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/discover_tests/COMMAND_EXPAND_LISTS-stdout.txt b/Tests/RunCMake/discover_tests/COMMAND_EXPAND_LISTS-stdout.txt
new file mode 100644
index 0000000..6995e16
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/COMMAND_EXPAND_LISTS-stdout.txt
@@ -0,0 +1,7 @@
+ Test #[0-9]*: ExpandLists.OFF.case_one;two
+ Test #[0-9]*: ExpandLists.OFF.case_three
+ Test #[0-9]*: ExpandLists.ON.case_one
+ Test #[0-9]*: ExpandLists.ON.case_two
+ Test #[0-9]*: ExpandLists.ON.case_three
+
+Total Tests: 5
diff --git a/Tests/RunCMake/discover_tests/ENVIRONMENT-stdout.txt b/Tests/RunCMake/discover_tests/ENVIRONMENT-stdout.txt
new file mode 100644
index 0000000..1657610
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/ENVIRONMENT-stdout.txt
@@ -0,0 +1,7 @@
+ Start [0-9]*: Env.case_two
+.*
+
+100% tests passed out of 1
+
+Label Time Summary:
+FOOBAR
diff --git a/Tests/RunCMake/discover_tests/PROPERTY-stdout.txt b/Tests/RunCMake/discover_tests/PROPERTY-stdout.txt
new file mode 100644
index 0000000..0b05156
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/PROPERTY-stdout.txt
@@ -0,0 +1,4 @@
+ Test #[0-9]*: DT.case_one
+ Test #[0-9]*: DT.case_three
+
+Total Tests: 2
diff --git a/Tests/RunCMake/discover_tests/RunCMakeTest.cmake b/Tests/RunCMake/discover_tests/RunCMakeTest.cmake
new file mode 100644
index 0000000..68c80be
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/RunCMakeTest.cmake
@@ -0,0 +1,37 @@
+include(RunCMake)
+
+# Isolate our ctest runs from external environment.
+unset(ENV{CTEST_PARALLEL_LEVEL})
+unset(ENV{CTEST_OUTPUT_ON_FAILURE})
+
+if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+endif()
+
+block()
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/basic-build")
+ run_cmake(basic)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(basic-build ${CMAKE_COMMAND} --build . --config Debug)
+
+ run_cmake_command(PROPERTY ${CMAKE_CTEST_COMMAND} -C Debug -N -L LBL1)
+
+ set(ENV{TEST_LABEL} "FOO")
+ run_cmake_command(ENVIRONMENT ${CMAKE_CTEST_COMMAND} -C Debug -R "Env.")
+
+ run_cmake_command(COMMAND_EXPAND_LISTS
+ ${CMAKE_CTEST_COMMAND} -C Debug -N -R "ExpandLists.")
+endblock()
+
+function(run_case CASE)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${CASE}-build)
+ run_cmake(${CASE})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${CASE}-build ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${CASE}-test ${CMAKE_CTEST_COMMAND} -C Debug)
+endfunction()
+
+run_case(bad-command)
+run_case(bad-regex)
+run_case(discovery-failure)
+run_case(discovery-timeout)
diff --git a/Tests/RunCMake/discover_tests/bad-command-test-result.txt b/Tests/RunCMake/discover_tests/bad-command-test-result.txt
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/bad-command-test-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/discover_tests/bad-command-test-stderr.txt b/Tests/RunCMake/discover_tests/bad-command-test-stderr.txt
new file mode 100644
index 0000000..231b307
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/bad-command-test-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .* \(discover_tests\):
+ discover_tests failed to run command:.*
+
+ no such file or directory
diff --git a/Tests/RunCMake/discover_tests/bad-command.cmake b/Tests/RunCMake/discover_tests/bad-command.cmake
new file mode 100644
index 0000000..0718468
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/bad-command.cmake
@@ -0,0 +1,11 @@
+enable_language(C)
+enable_testing()
+
+add_executable(fake_discovery fake_discovery.c)
+
+discover_tests(COMMAND fake_discovery_notfound
+ DISCOVERY_ARGS --list
+ DISCOVERY_MATCH "^([^,]+),([^,]+)$"
+ TEST_NAME "DT.\\1"
+ TEST_ARGS --run "\\1"
+)
diff --git a/Tests/RunCMake/discover_tests/bad-regex-test-result.txt b/Tests/RunCMake/discover_tests/bad-regex-test-result.txt
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/bad-regex-test-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/discover_tests/bad-regex-test-stderr.txt b/Tests/RunCMake/discover_tests/bad-regex-test-stderr.txt
new file mode 100644
index 0000000..2380d40
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/bad-regex-test-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at .* \(discover_tests\):
+ discover_tests DISCOVERY_MATCH failed to compile regex "\(".
diff --git a/Tests/RunCMake/discover_tests/bad-regex.cmake b/Tests/RunCMake/discover_tests/bad-regex.cmake
new file mode 100644
index 0000000..6acc44a
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/bad-regex.cmake
@@ -0,0 +1,11 @@
+enable_language(C)
+enable_testing()
+
+add_executable(fake_discovery fake_discovery.c)
+
+discover_tests(COMMAND fake_discovery
+ DISCOVERY_ARGS --list
+ DISCOVERY_MATCH "("
+ TEST_NAME "DT.\\1"
+ TEST_ARGS --run "\\1"
+)
diff --git a/Tests/RunCMake/discover_tests/basic.cmake b/Tests/RunCMake/discover_tests/basic.cmake
new file mode 100644
index 0000000..88e00c3
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/basic.cmake
@@ -0,0 +1,39 @@
+enable_language(C)
+enable_testing()
+
+add_executable(fake_discovery fake_discovery.c)
+
+discover_tests(COMMAND fake_discovery
+ DISCOVERY_ARGS --list_tests
+ DISCOVERY_MATCH "^([^,]+),([^,]+)$"
+ TEST_NAME "DT.\\1"
+ TEST_ARGS "\\1"
+ TEST_PROPERTIES
+ LABELS "\\2"
+)
+
+discover_tests(COMMAND fake_discovery
+ DISCOVERY_ARGS --list_env
+ DISCOVERY_MATCH "^([^,]+),([^,]+)$"
+ DISCOVERY_PROPERTIES
+ ENVIRONMENT "TEST_NAME=two"
+ ENVIRONMENT_MODIFICATION "TEST_LABEL=string_append:BAR"
+ TEST_NAME "Env.\\1"
+ TEST_ARGS "\\1"
+ TEST_PROPERTIES
+ LABELS "\\2"
+)
+
+discover_tests(COMMAND fake_discovery --list_args "one;two"
+ DISCOVERY_ARGS "three"
+ DISCOVERY_MATCH ".*"
+ TEST_NAME "ExpandLists.OFF.\\0"
+ TEST_ARGS ""
+)
+
+discover_tests(COMMAND fake_discovery --list_args "one;two" COMMAND_EXPAND_LISTS
+ DISCOVERY_ARGS "three"
+ DISCOVERY_MATCH ".*"
+ TEST_NAME "ExpandLists.ON.\\0"
+ TEST_ARGS ""
+)
diff --git a/Tests/RunCMake/discover_tests/discovery-failure-test-result.txt b/Tests/RunCMake/discover_tests/discovery-failure-test-result.txt
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/discovery-failure-test-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/discover_tests/discovery-failure-test-stderr.txt b/Tests/RunCMake/discover_tests/discovery-failure-test-stderr.txt
new file mode 100644
index 0000000..7f46757
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/discovery-failure-test-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .* \(discover_tests\):
+ discover_tests failed to run command:.*
+
+ discovery failure
diff --git a/Tests/RunCMake/discover_tests/discovery-failure.cmake b/Tests/RunCMake/discover_tests/discovery-failure.cmake
new file mode 100644
index 0000000..57eb9d2
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/discovery-failure.cmake
@@ -0,0 +1,13 @@
+enable_language(C)
+enable_testing()
+
+add_executable(fake_discovery fake_discovery.c)
+
+discover_tests(COMMAND fake_discovery
+ DISCOVERY_ARGS --list_fail
+ DISCOVERY_MATCH "^([^,]+),([^,]+)$"
+ TEST_NAME "DT.\\1"
+ TEST_ARGS "\\1"
+ TEST_PROPERTIES
+ LABELS "\\2"
+)
diff --git a/Tests/RunCMake/discover_tests/discovery-timeout-test-result.txt b/Tests/RunCMake/discover_tests/discovery-timeout-test-result.txt
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/discovery-timeout-test-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/discover_tests/discovery-timeout-test-stderr.txt b/Tests/RunCMake/discover_tests/discovery-timeout-test-stderr.txt
new file mode 100644
index 0000000..ceb29f2
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/discovery-timeout-test-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .* \(discover_tests\):
+ discover_tests failed to run command:.*
+
+ Process terminated due to timeout
diff --git a/Tests/RunCMake/discover_tests/discovery-timeout.cmake b/Tests/RunCMake/discover_tests/discovery-timeout.cmake
new file mode 100644
index 0000000..6655b14
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/discovery-timeout.cmake
@@ -0,0 +1,15 @@
+enable_language(C)
+enable_testing()
+
+add_executable(fake_discovery fake_discovery.c)
+
+discover_tests(COMMAND fake_discovery
+ DISCOVERY_ARGS --list_timeout
+ DISCOVERY_MATCH "^([^,]+),([^,]+)$"
+ DISCOVERY_PROPERTIES
+ TIMEOUT "0.1"
+ TEST_NAME "DT.\\1"
+ TEST_ARGS "\\1"
+ TEST_PROPERTIES
+ LABELS "\\2"
+)
diff --git a/Tests/RunCMake/discover_tests/fake_discovery.c b/Tests/RunCMake/discover_tests/fake_discovery.c
new file mode 100644
index 0000000..722072c
--- /dev/null
+++ b/Tests/RunCMake/discover_tests/fake_discovery.c
@@ -0,0 +1,111 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file LICENSE.rst or https://cmake.org/licensing for details. */
+
+#if defined(_MSC_VER)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_WIN32)
+# include <windows.h>
+#else
+# include <unistd.h>
+#endif
+
+static int list_tests(int ac, char** av)
+{
+ (void)ac, (void)av;
+ printf("this line should not match\n");
+ printf("case_one,LBL1\n");
+ printf("\n");
+ printf("case_two,LBL2\n");
+ printf("garbage,still,has,commas\n");
+ printf("case_three,LBL1\n");
+ return 0;
+}
+
+static int list_fail(int ac, char** av)
+{
+ (void)ac, (void)av;
+ fprintf(stderr, "discovery failure\n");
+ return -1;
+}
+
+static int list_timeout(int ac, char** av)
+{
+ (void)ac, (void)av;
+ printf("case_one,LBL1\n");
+#if defined(_WIN32)
+ Sleep(5000);
+#else
+ sleep(5);
+#endif
+ return 0;
+}
+
+static int list_args(int ac, char** av)
+{
+ int i;
+ for (i = 0; i < ac; i++) {
+ printf("case_%s\n", av[i]);
+ }
+ return 0;
+}
+
+static int list_env(int ac, char** av)
+{
+ (void)ac, (void)av;
+ printf("case_%s,%s\n", getenv("TEST_NAME"), getenv("TEST_LABEL"));
+ return 0;
+}
+
+static int success(int ac, char** av)
+{
+ (void)ac, (void)av;
+ return 0;
+}
+
+typedef int (*function_ptr)(int, char**);
+
+struct function_entry
+{
+ char const* name;
+ function_ptr function;
+};
+
+struct function_entry const function_map[] = {
+ { "--list_tests", list_tests },
+ { "--list_fail", list_fail },
+ { "--list_timeout", list_timeout },
+ { "--list_args", list_args },
+ { "--list_env", list_env },
+ { "case_one", success },
+ { "case_two", success },
+ { "case_three", success },
+ { NULL, NULL },
+};
+
+static function_ptr lookup(char const* name)
+{
+ struct function_entry const* it = function_map;
+ for (; it->name != NULL; ++it) {
+ if (strcmp(name, it->name) == 0) {
+ return it->function;
+ }
+ }
+ return NULL;
+}
+
+int main(int argc, char** argv)
+{
+ function_ptr fn = argc > 1 ? lookup(argv[1]) : NULL;
+ if (fn == NULL) {
+ fprintf(stderr, "invalid argument\n");
+ return -1;
+ }
+
+ return fn(argc - 2, argv + 2);
+}
diff --git a/Tests/RunCMake/execute_process/Environment-stdout.txt b/Tests/RunCMake/execute_process/Environment-stdout.txt
new file mode 100644
index 0000000..747b1ab
--- /dev/null
+++ b/Tests/RunCMake/execute_process/Environment-stdout.txt
@@ -0,0 +1 @@
+CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=expected_value
diff --git a/Tests/RunCMake/execute_process/Environment.cmake b/Tests/RunCMake/execute_process/Environment.cmake
new file mode 100644
index 0000000..86273b5
--- /dev/null
+++ b/Tests/RunCMake/execute_process/Environment.cmake
@@ -0,0 +1,5 @@
+execute_process(
+ COMMAND ${CMAKE_COMMAND} -E environment
+ ENVIRONMENT
+ "CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=expected_value"
+ )
diff --git a/Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt b/Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt
new file mode 100644
index 0000000..eb07dc9
--- /dev/null
+++ b/Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt
@@ -0,0 +1 @@
+CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=kaesekuchen
diff --git a/Tests/RunCMake/execute_process/EnvironmentModification.cmake b/Tests/RunCMake/execute_process/EnvironmentModification.cmake
new file mode 100644
index 0000000..cd23fd3
--- /dev/null
+++ b/Tests/RunCMake/execute_process/EnvironmentModification.cmake
@@ -0,0 +1,6 @@
+set(ENV{CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT} "kaese")
+execute_process(
+ COMMAND ${CMAKE_COMMAND} -E environment
+ ENVIRONMENT_MODIFICATION
+ "CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=string_append:kuchen"
+ )
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-result.txt b/Tests/RunCMake/execute_process/EnvironmentModificationError-result.txt
similarity index 100%
copy from Tests/RunCMake/target_sources/FileSetFramework-result.txt
copy to Tests/RunCMake/execute_process/EnvironmentModificationError-result.txt
diff --git a/Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt b/Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt
new file mode 100644
index 0000000..a3d4c09
--- /dev/null
+++ b/Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt
@@ -0,0 +1 @@
+CMake Error: Error: Unrecognized environment manipulation argument: invalid
diff --git a/Tests/RunCMake/execute_process/EnvironmentModificationError.cmake b/Tests/RunCMake/execute_process/EnvironmentModificationError.cmake
new file mode 100644
index 0000000..9a9a7ed
--- /dev/null
+++ b/Tests/RunCMake/execute_process/EnvironmentModificationError.cmake
@@ -0,0 +1,5 @@
+execute_process(
+ COMMAND ${CMAKE_COMMAND} -E environment
+ ENVIRONMENT_MODIFICATION
+ "CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=invalid:value"
+ )
diff --git a/Tests/RunCMake/execute_process/RunCMakeTest.cmake b/Tests/RunCMake/execute_process/RunCMakeTest.cmake
index 973ff12..3137d66 100644
--- a/Tests/RunCMake/execute_process/RunCMakeTest.cmake
+++ b/Tests/RunCMake/execute_process/RunCMakeTest.cmake
@@ -19,6 +19,10 @@
run_cmake_script(EncodingUTF8 -DTEST_ENCODING_EXE=${TEST_ENCODING_EXE})
endif()
+run_cmake(Environment)
+run_cmake(EnvironmentModification)
+run_cmake(EnvironmentModificationError)
+
if(EXIT_CODE_EXE)
run_cmake_command(ExitValues ${CMAKE_COMMAND} -DEXIT_CODE_EXE=${EXIT_CODE_EXE} -P ${RunCMake_SOURCE_DIR}/ExitValues.cmake)
endif()
diff --git a/Tests/RunCMake/exit_crash.c b/Tests/RunCMake/exit_crash.c
index 3872abe..caa5377 100644
--- a/Tests/RunCMake/exit_crash.c
+++ b/Tests/RunCMake/exit_crash.c
@@ -1,3 +1,7 @@
+#ifdef __POCC__
+# pragma warn(disable : 2801) /* Store to a non-writable location. */
+#endif
+
int main(int argc, char const* argv[])
{
#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
diff --git a/Tests/RunCMake/file/REAL_PATH-stderr.txt b/Tests/RunCMake/file/REAL_PATH-stderr.txt
new file mode 100644
index 0000000..1fd78d6
--- /dev/null
+++ b/Tests/RunCMake/file/REAL_PATH-stderr.txt
@@ -0,0 +1,10 @@
+^(CMake Deprecation Warning at REAL_PATH\.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0152 will be removed from a future version
+ of CMake\.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances\. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\))?$
diff --git a/Tests/RunCMake/install/FILES-DESTINATION-dot-all-stdout.txt b/Tests/RunCMake/install/FILES-DESTINATION-dot-all-stdout.txt
new file mode 100644
index 0000000..d9fde44
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-DESTINATION-dot-all-stdout.txt
@@ -0,0 +1,2 @@
+-- Installing: [^
+]+/Tests/RunCMake/install/FILES-DESTINATION-dot-build/root-all/empty\.c
diff --git a/Tests/RunCMake/install/FILES-DESTINATION-dot.cmake b/Tests/RunCMake/install/FILES-DESTINATION-dot.cmake
new file mode 100644
index 0000000..eb3b0d5
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-DESTINATION-dot.cmake
@@ -0,0 +1 @@
+install(FILES empty.c DESTINATION ".")
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index 818b898..ff8e812 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -127,6 +127,7 @@
run_install_test(FILES-EXTRA_ISPC_TARGET_OBJECTS)
endif()
+run_install_test(FILES-DESTINATION-dot)
run_install_test(TARGETS-InstallFromSubDir)
run_install_test(TARGETS-OPTIONAL)
@@ -214,6 +215,8 @@
unset(RunCMake_TEST_OPTIONS)
run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict)
run_cmake(RuntimeDependencies-COMPONENTS)
+ run_cmake(RuntimeDependencies-Default-COMPONENT-Name)
+ run_cmake(RuntimeDependencies-ProjectName-Placeholder-COMPONENT-Name)
else()
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported)
run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-unsupported)
diff --git a/Tests/RunCMake/install/RuntimeDependencies-Default-COMPONENT-Name.cmake b/Tests/RunCMake/install/RuntimeDependencies-Default-COMPONENT-Name.cmake
new file mode 100644
index 0000000..47e8f36
--- /dev/null
+++ b/Tests/RunCMake/install/RuntimeDependencies-Default-COMPONENT-Name.cmake
@@ -0,0 +1,21 @@
+enable_language(C)
+
+function(check_components value)
+ get_cmake_property(comp COMPONENTS)
+ if(NOT comp STREQUAL value)
+ message(FATAL_ERROR "Expected value of COMPONENTS:\n ${value}\nActual value of COMPONENTS:\n ${comp}")
+ endif()
+endfunction()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_library(tgt MODULE obj1.c)
+else()
+ add_executable(tgt main.c)
+endif()
+
+set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "default_name")
+install(TARGETS tgt
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ )
+check_components("default_name")
diff --git a/Tests/RunCMake/install/RuntimeDependencies-ProjectName-Placeholder-COMPONENT-Name.cmake b/Tests/RunCMake/install/RuntimeDependencies-ProjectName-Placeholder-COMPONENT-Name.cmake
new file mode 100644
index 0000000..6701bcc
--- /dev/null
+++ b/Tests/RunCMake/install/RuntimeDependencies-ProjectName-Placeholder-COMPONENT-Name.cmake
@@ -0,0 +1,28 @@
+enable_language(C)
+
+function(check_components value)
+ get_cmake_property(comp COMPONENTS)
+ if(NOT comp STREQUAL value)
+ message(FATAL_ERROR "Expected value of COMPONENTS:\n ${value}\nActual value of COMPONENTS:\n ${comp}")
+ endif()
+endfunction()
+
+project(hello_world)
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_library(tgt MODULE obj1.c)
+ add_library(tgt2 MODULE obj1.c)
+else()
+ add_executable(tgt main.c)
+ add_executable(tgt2 main.c)
+endif()
+
+set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "<PROJECT_NAME>")
+install(TARGETS tgt
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ )
+install(TARGETS tgt2
+ RUNTIME DESTINATION bin COMPONENT "other"
+ LIBRARY DESTINATION lib COMPONENT "other"
+ )
+check_components("hello_world;other")
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
index 930ef70..12648fa 100644
--- a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
@@ -29,7 +29,7 @@
set(target "exe2_cmp0095_new")
string(CONCAT regex "${prefix}${target}\"${wssl}"
- [[NEW_RPATH "\\\$ORIGIN/../lib]])
+ [[NEW_RPATH \[\[\$ORIGIN/../lib]])
check()
set(target "exe3_cmp0095_old")
@@ -44,7 +44,7 @@
set(target "exe3_cmp0095_new")
string(CONCAT regex "${prefix}${target}\"${wssl}"
- [[NEW_RPATH "\\\${ORIGIN}/../lib]])
+ [[NEW_RPATH \[\[\${ORIGIN}/../lib]])
check()
set(target "exe4_cmp0095_old")
@@ -59,5 +59,5 @@
set(target "exe4_cmp0095_new")
string(CONCAT regex "${prefix}${target}\"${wssl}"
- [[NEW_RPATH "/foo/bar/\\\${PLATFORM}]])
+ [[NEW_RPATH \[\[/foo/bar/\${PLATFORM}]])
check()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
index f45b303..90fc03d 100644
--- a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
@@ -11,6 +11,6 @@
if("x${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}" STREQUAL "x\$ORIGIN")
set(target "exe2")
string(CONCAT regex "${prefix}${target}\"${wsnl}"
- [[OLD_RPATH "\\\$ORIGIN]])
+ [[OLD_RPATH \[\[\$ORIGIN]])
check()
endif()
diff --git a/Tests/RunCMake/math/Overflow-stderr.txt b/Tests/RunCMake/math/Overflow-stderr.txt
new file mode 100644
index 0000000..01ffffe
--- /dev/null
+++ b/Tests/RunCMake/math/Overflow-stderr.txt
@@ -0,0 +1,71 @@
+^CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ left shift of negative value in:
+
+ -4 << 1
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ shift exponent is negative in:
+
+ 4 << -63
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ shift exponent is negative in:
+
+ 4 >> -63
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ shift exponent is too large in:
+
+ 4 << 65
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ shift exponent is too large in:
+
+ 4 >> 65
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ signed integer overflow in:
+
+ 9223372036854775807 \+ 1
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ signed integer overflow in:
+
+ -9223372036854775807 - 2
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ signed integer overflow in:
+
+ 9223372036854775807 \* 2
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at [^
+]+/Tests/RunCMake/math/Overflow\.cmake:[0-9]+ \(math\):
+ signed integer cannot negate:
+
+ -9223372036854775808
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/math/Overflow-stdout.txt b/Tests/RunCMake/math/Overflow-stdout.txt
new file mode 100644
index 0000000..5bcdcca
--- /dev/null
+++ b/Tests/RunCMake/math/Overflow-stdout.txt
@@ -0,0 +1,10 @@
+^-- -4 << 1: -8
+-- -4 >> 1: -2
+-- 4 << -63: 8
+-- 4 >> -63: 2
+-- 4 << 65: 8
+-- 4 >> 65: 2
+-- 0x7FFFFFFFFFFFFFFF \+ 1: -9223372036854775808
+-- -0x7FFFFFFFFFFFFFFF - 2: 9223372036854775807
+-- 0x7FFFFFFFFFFFFFFF \* 2: -2
+-- -~0x7FFFFFFFFFFFFFFF: -9223372036854775808$
diff --git a/Tests/RunCMake/math/Overflow.cmake b/Tests/RunCMake/math/Overflow.cmake
new file mode 100644
index 0000000..c5a7464
--- /dev/null
+++ b/Tests/RunCMake/math/Overflow.cmake
@@ -0,0 +1,15 @@
+foreach(expr IN ITEMS
+ "-4 << 1"
+ "-4 >> 1"
+ " 4 << -63"
+ " 4 >> -63"
+ " 4 << 65"
+ " 4 >> 65"
+ " 0x7FFFFFFFFFFFFFFF + 1"
+ "-0x7FFFFFFFFFFFFFFF - 2"
+ " 0x7FFFFFFFFFFFFFFF * 2"
+ "-~0x7FFFFFFFFFFFFFFF"
+ )
+ math(EXPR result "${expr}")
+ message(STATUS "${expr}: ${result}")
+endforeach()
diff --git a/Tests/RunCMake/math/RunCMakeTest.cmake b/Tests/RunCMake/math/RunCMakeTest.cmake
index 88e7bd0..cda0094 100644
--- a/Tests/RunCMake/math/RunCMakeTest.cmake
+++ b/Tests/RunCMake/math/RunCMakeTest.cmake
@@ -8,3 +8,7 @@
run_cmake(MATH-ToleratedExpression)
run_cmake(MATH-DivideByZero)
run_cmake(MATH-ModByZero)
+
+if(CMake_TEST_MATH_OVERFLOW)
+ run_cmake_script(Overflow)
+endif()
diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake
index 786b49b..05dd6a6 100644
--- a/Tests/RunCMake/message/RunCMakeTest.cmake
+++ b/Tests/RunCMake/message/RunCMakeTest.cmake
@@ -7,9 +7,18 @@
run_cmake(defaultmessage)
run_cmake(nomessage)
run_cmake(message-internal-warning)
-run_cmake(nomessage-internal-warning)
+# run_cmake(nomessage-internal-warning)
run_cmake(warnmessage)
+# TODO: We currently do not have a way to change diagnostic state in a way that
+# is visible to internally issued diagnostic. This will be remedied when we
+# switch to the new methods for issuing diagnostics, but for a brief window,
+# this test will only pass if author warnings are disabled by command-line
+# option.
+set(RunCMake_TEST_OPTIONS -Wno-author)
+run_cmake(nomessage-internal-warning)
+unset(RunCMake_TEST_OPTIONS)
+
# Have to explicitly give the command for the working dir to be honored
set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY /)
run_cmake_command(
diff --git a/Tests/RunCMake/message/errormessage_deprecated.cmake b/Tests/RunCMake/message/errormessage_deprecated.cmake
index 579275e..76429ea 100644
--- a/Tests/RunCMake/message/errormessage_deprecated.cmake
+++ b/Tests/RunCMake/message/errormessage_deprecated.cmake
@@ -1,3 +1,3 @@
-set(CMAKE_ERROR_DEPRECATED ON)
+cmake_diagnostic(SET CMD_DEPRECATED SEND_ERROR)
message(DEPRECATION "This is a deprecation error")
diff --git a/Tests/RunCMake/message/errormessage_dev.cmake b/Tests/RunCMake/message/errormessage_dev.cmake
index 6ba1165..405e891 100644
--- a/Tests/RunCMake/message/errormessage_dev.cmake
+++ b/Tests/RunCMake/message/errormessage_dev.cmake
@@ -1,3 +1,3 @@
-set(CMAKE_SUPPRESS_DEVELOPER_ERRORS OFF)
+cmake_diagnostic(SET CMD_AUTHOR SEND_ERROR)
message(AUTHOR_WARNING "This is a author error")
diff --git a/Tests/RunCMake/message/message-internal-warning.cmake b/Tests/RunCMake/message/message-internal-warning.cmake
index 33993c7..f549988 100644
--- a/Tests/RunCMake/message/message-internal-warning.cmake
+++ b/Tests/RunCMake/message/message-internal-warning.cmake
@@ -1,5 +1,5 @@
-set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ON)
+cmake_diagnostic(SET CMD_AUTHOR WARN)
macro(mymacro)
endmacro(notmymacro)
diff --git a/Tests/RunCMake/message/nomessage-internal-warning.cmake b/Tests/RunCMake/message/nomessage-internal-warning.cmake
index 3ec2e28..a5d3cea 100644
--- a/Tests/RunCMake/message/nomessage-internal-warning.cmake
+++ b/Tests/RunCMake/message/nomessage-internal-warning.cmake
@@ -1,5 +1,5 @@
-set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ON CACHE BOOL "")
+cmake_diagnostic(SET CMD_AUTHOR IGNORE)
macro(mymacro)
endmacro(notmymacro)
diff --git a/Tests/RunCMake/message/nomessage.cmake b/Tests/RunCMake/message/nomessage.cmake
index 78f4769..b793293 100644
--- a/Tests/RunCMake/message/nomessage.cmake
+++ b/Tests/RunCMake/message/nomessage.cmake
@@ -1,8 +1,8 @@
-set(CMAKE_WARN_DEPRECATED OFF)
+cmake_diagnostic(SET CMD_DEPRECATED IGNORE)
message(DEPRECATION "This is not issued")
-set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ON)
+cmake_diagnostic(SET CMD_AUTHOR IGNORE)
message(AUTHOR_WARNING "This is not issued")
diff --git a/Tests/RunCMake/message/warnmessage.cmake b/Tests/RunCMake/message/warnmessage.cmake
index 53f2a43..0792aec 100644
--- a/Tests/RunCMake/message/warnmessage.cmake
+++ b/Tests/RunCMake/message/warnmessage.cmake
@@ -1,8 +1,8 @@
-set(CMAKE_WARN_DEPRECATED ON)
+cmake_diagnostic(SET CMD_DEPRECATED WARN)
message(DEPRECATION "This is a deprecation warning")
-set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS OFF)
+cmake_diagnostic(SET CMD_AUTHOR WARN)
message(AUTHOR_WARNING "This is a author warning")
diff --git a/Tests/RunCMake/set_property/Common.cmake b/Tests/RunCMake/set_property/Common.cmake
index 3aa78ed..0673bc8 100644
--- a/Tests/RunCMake/set_property/Common.cmake
+++ b/Tests/RunCMake/set_property/Common.cmake
@@ -1,3 +1,5 @@
+enable_language(C)
+
macro(test_target_property PROP)
add_custom_target(CustomTarget)
set_property(TARGET CustomTarget PROPERTY ${PROP} x)
@@ -28,8 +30,8 @@
endmacro()
macro(test_file_set_property PROP)
- add_library(foo INTERFACE)
- target_sources(foo INTERFACE FILE_SET foo TYPE HEADERS)
+ add_library(foo STATIC foo.c)
+ target_sources(foo PRIVATE FILE_SET foo TYPE HEADERS)
set_property(FILE_SET foo TARGET foo PROPERTY ${PROP} x)
set_property(FILE_SET foo TARGET foo PROPERTY ${PROP})
set_property(FILE_SET foo TARGET foo APPEND PROPERTY ${PROP})
diff --git a/Tests/RunCMake/set_property/foo.c b/Tests/RunCMake/set_property/foo.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/set_property/foo.c
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
deleted file mode 100644
index 9d5875d..0000000
--- a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-^CMake Error:.*CMake can not determine linker language for target: main.*
-CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake b/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake
index b7e9119..a0a2363 100644
--- a/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake
+++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake
@@ -1,2 +1,3 @@
+enable_language(C)
add_executable(main empty.c)
target_compile_features(main PRIVATE cxx_decltype)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake
index 6dbadaa..e0af6af 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake
@@ -63,7 +63,7 @@
endif()
# Feature RESCAN
-if (CMAKE_SYSTEM_NAME MATCHES "Linux|BSD"
+if (CMAKE_SYSTEM_NAME MATCHES "Linux|BSD|Haiku"
OR (CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND (NOT CMAKE_C_COMPILER_ID STREQUAL "SunPro" OR CMAKE_C_COMPILER_VERSION VERSION_GREATER "5.9"))
OR (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "GNU"))
run_cmake(rescan)
diff --git a/Tests/RunCMake/target_sources/CMP0211-Common.cmake b/Tests/RunCMake/target_sources/CMP0211-Common.cmake
new file mode 100644
index 0000000..6a8978b
--- /dev/null
+++ b/Tests/RunCMake/target_sources/CMP0211-Common.cmake
@@ -0,0 +1,9 @@
+
+enable_language(C)
+
+add_library(foo1 STATIC lib1.c)
+target_sources(foo1 PRIVATE FILE_SET h1 TYPE HEADERS FILES h1.h)
+target_sources(foo1 PRIVATE FILE_SET h2 TYPE HEADERS FILES h1.h)
+
+add_library(foo2 STATIC lib1.c h1.h)
+target_sources(foo2 PRIVATE FILE_SET h1 TYPE HEADERS FILES h1.h)
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-result.txt b/Tests/RunCMake/target_sources/CMP0211-NEW-result.txt
similarity index 100%
rename from Tests/RunCMake/target_sources/FileSetFramework-result.txt
rename to Tests/RunCMake/target_sources/CMP0211-NEW-result.txt
diff --git a/Tests/RunCMake/target_sources/CMP0211-NEW-stderr.txt b/Tests/RunCMake/target_sources/CMP0211-NEW-stderr.txt
new file mode 100644
index 0000000..4ba13b3
--- /dev/null
+++ b/Tests/RunCMake/target_sources/CMP0211-NEW-stderr.txt
@@ -0,0 +1,14 @@
+CMake Error in CMakeLists\.txt:
+ In target "foo1" the file
+
+ .+/Tests/RunCMake/target_sources/h1\.h
+
+ already belongs to file set "h2"\.
+
+
+CMake Error in CMakeLists\.txt:
+ In target "foo2" the file
+
+ .+/Tests/RunCMake/target_sources/h1\.h
+
+ already belongs to file set "h1"\.
diff --git a/Tests/RunCMake/target_sources/CMP0211-NEW.cmake b/Tests/RunCMake/target_sources/CMP0211-NEW.cmake
new file mode 100644
index 0000000..4d42024
--- /dev/null
+++ b/Tests/RunCMake/target_sources/CMP0211-NEW.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0211 NEW)
+
+include(CMP0211-Common.cmake)
diff --git a/Tests/RunCMake/target_sources/CMP0211-OLD.cmake b/Tests/RunCMake/target_sources/CMP0211-OLD.cmake
new file mode 100644
index 0000000..4e32f39
--- /dev/null
+++ b/Tests/RunCMake/target_sources/CMP0211-OLD.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0211 OLD)
+
+include(CMP0211-Common.cmake)
diff --git a/Tests/RunCMake/target_sources/CMP0211-WARN-stderr.txt b/Tests/RunCMake/target_sources/CMP0211-WARN-stderr.txt
new file mode 100644
index 0000000..4f7664f
--- /dev/null
+++ b/Tests/RunCMake/target_sources/CMP0211-WARN-stderr.txt
@@ -0,0 +1,23 @@
+CMake Warning \(dev\) in CMakeLists\.txt:
+ Policy CMP0211 is not set: A file may belong to at most one file set in a
+ target\. Run "cmake --help-policy CMP0211" for policy details\. Use the
+ cmake_policy command to set the policy and suppress this warning\.
+
+ In target "foo1" the file
+
+ .+/Tests/RunCMake/target_sources/h1\.h
+
+ already belongs to file set "h2"\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) in CMakeLists\.txt:
+ Policy CMP0211 is not set: A file may belong to at most one file set in a
+ target\. Run "cmake --help-policy CMP0211" for policy details\. Use the
+ cmake_policy command to set the policy and suppress this warning\.
+
+ In target "foo2" the file
+
+ .+/Tests/RunCMake/target_sources/h1\.h
+
+ already belongs to file set "h1"\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/target_sources/CMP0211-WARN.cmake b/Tests/RunCMake/target_sources/CMP0211-WARN.cmake
new file mode 100644
index 0000000..78fa4b3
--- /dev/null
+++ b/Tests/RunCMake/target_sources/CMP0211-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0211-Common.cmake)
diff --git a/Tests/RunCMake/target_sources/FileSetChangeType-stderr.txt b/Tests/RunCMake/target_sources/FileSetChangeType-stderr.txt
index 85fc718..3fd5a97 100644
--- a/Tests/RunCMake/target_sources/FileSetChangeType-stderr.txt
+++ b/Tests/RunCMake/target_sources/FileSetChangeType-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error at FileSetChangeType\.cmake:[0-9]+ \(target_sources\):
- target_sources Type "RESOURCES" for file set "a" does not match original
+ target_sources Type "CXX_MODULES" for file set "a" does not match original
type "HEADERS"
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetChangeType.cmake b/Tests/RunCMake/target_sources/FileSetChangeType.cmake
index 69eb6bc..75b11e4 100644
--- a/Tests/RunCMake/target_sources/FileSetChangeType.cmake
+++ b/Tests/RunCMake/target_sources/FileSetChangeType.cmake
@@ -2,4 +2,4 @@
add_library(lib1 STATIC empty.c)
target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS)
-target_sources(lib1 PRIVATE FILE_SET a TYPE RESOURCES)
+target_sources(lib1 PRIVATE FILE_SET a TYPE CXX_MODULES)
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongType-stderr.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongType-stderr.txt
index c13c8a8..85da541 100644
--- a/Tests/RunCMake/target_sources/FileSetDefaultWrongType-stderr.txt
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongType-stderr.txt
@@ -1,4 +1,5 @@
^CMake Error at FileSetDefaultWrongType\.cmake:[0-9]+ \(target_sources\):
- target_sources File set TYPE may only be "HEADERS" or "CXX_MODULES"
+ target_sources FILE_SET names starting with a capital letter are reserved
+ for built-in file sets and may only be "HEADERS", "SOURCES", "CXX_MODULES"
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetDuplicateSource.cmake b/Tests/RunCMake/target_sources/FileSetDuplicateSource.cmake
new file mode 100644
index 0000000..6fb1ab3
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDuplicateSource.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+add_library(lib1 STATIC empty.c)
+
+# files are silently de-duplicated
+target_sources(lib1 PRIVATE FILE_SET HEADERS FILES h1.h h1.h)
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-stderr.txt b/Tests/RunCMake/target_sources/FileSetFramework-stderr.txt
deleted file mode 100644
index ae7026a..0000000
--- a/Tests/RunCMake/target_sources/FileSetFramework-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-^CMake Error at FileSetFramework\.cmake:[0-9]+ \(target_sources\):
- target_sources FILE_SETs may not be added to FRAMEWORK targets
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-result.txt b/Tests/RunCMake/target_sources/FileSetFramework1-result.txt
similarity index 100%
copy from Tests/RunCMake/target_sources/FileSetFramework-result.txt
copy to Tests/RunCMake/target_sources/FileSetFramework1-result.txt
diff --git a/Tests/RunCMake/target_sources/FileSetFramework1-stderr.txt b/Tests/RunCMake/target_sources/FileSetFramework1-stderr.txt
new file mode 100644
index 0000000..5a2e65a
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetFramework1-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at FileSetFramework1\.cmake:[0-9]+ \(target_sources\):
+ target_sources FILE_SETs, of type "HEADERS", may not be added to FRAMEWORK
+ targets
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetFramework.cmake b/Tests/RunCMake/target_sources/FileSetFramework1.cmake
similarity index 100%
rename from Tests/RunCMake/target_sources/FileSetFramework.cmake
rename to Tests/RunCMake/target_sources/FileSetFramework1.cmake
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-result.txt b/Tests/RunCMake/target_sources/FileSetFramework2-result.txt
similarity index 100%
copy from Tests/RunCMake/target_sources/FileSetFramework-result.txt
copy to Tests/RunCMake/target_sources/FileSetFramework2-result.txt
diff --git a/Tests/RunCMake/target_sources/FileSetFramework2-stderr.txt b/Tests/RunCMake/target_sources/FileSetFramework2-stderr.txt
new file mode 100644
index 0000000..5c54059
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetFramework2-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error in CMakeLists\.txt:
+ The file set "HEADERS", of type "HEADERS", is incompatible with the
+ "FRAMEWORK" target "lib1"\.
diff --git a/Tests/RunCMake/target_sources/FileSetFramework2.cmake b/Tests/RunCMake/target_sources/FileSetFramework2.cmake
new file mode 100644
index 0000000..6d89d41
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetFramework2.cmake
@@ -0,0 +1,7 @@
+enable_language(C)
+
+add_library(lib1 SHARED lib1.c)
+target_sources(lib1
+ PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES h1.h
+ )
+set_property(TARGET lib1 PROPERTY FRAMEWORK ON)
diff --git a/Tests/RunCMake/target_sources/FileSetFramework-result.txt b/Tests/RunCMake/target_sources/FileSetIncompatibleScopes-result.txt
similarity index 100%
copy from Tests/RunCMake/target_sources/FileSetFramework-result.txt
copy to Tests/RunCMake/target_sources/FileSetIncompatibleScopes-result.txt
diff --git a/Tests/RunCMake/target_sources/FileSetIncompatibleScopes-stderr.txt b/Tests/RunCMake/target_sources/FileSetIncompatibleScopes-stderr.txt
new file mode 100644
index 0000000..9a6d7fd
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetIncompatibleScopes-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at FileSetIncompatibleScopes\.cmake:[0-9]+ \(target_sources\):
+ target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
+ "PRIVATE" scope on INTERFACE libraries\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
+
+
+CMake Error at FileSetIncompatibleScopes\.cmake:[0-9]+ \(target_sources\):
+ target_sources File set TYPE "SOURCES" may not have "PUBLIC" or "PRIVATE"
+ scope on INTERFACE libraries\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_sources/FileSetIncompatibleScopes.cmake b/Tests/RunCMake/target_sources/FileSetIncompatibleScopes.cmake
new file mode 100644
index 0000000..d183f29
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetIncompatibleScopes.cmake
@@ -0,0 +1,5 @@
+enable_language(C)
+
+add_library(lib1 INTERFACE)
+target_sources(lib1 PUBLIC FILE_SET CXX_MODULES FILES lib1.c)
+target_sources(lib1 PUBLIC FILE_SET SOURCES FILES lib2.c)
diff --git a/Tests/RunCMake/target_sources/FileSetProperties.cmake b/Tests/RunCMake/target_sources/FileSetProperties.cmake
index 56cce08..8753eb6 100644
--- a/Tests/RunCMake/target_sources/FileSetProperties.cmake
+++ b/Tests/RunCMake/target_sources/FileSetProperties.cmake
@@ -56,20 +56,20 @@
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>")
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
-target_sources(lib1 PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES h1.h)
+target_sources(lib1 PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES h4.h)
assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS")
assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
-assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h")
+assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h4.h")
assert_prop_eq(lib1 HEADER_DIRS_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}")
-assert_prop_eq(lib1 HEADER_SET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/h1.h")
+assert_prop_eq(lib1 HEADER_SET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/h4.h")
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
-target_sources(lib1 PUBLIC FILE_SET HEADERS FILES h2.h)
+target_sources(lib1 PUBLIC FILE_SET HEADERS FILES h5.h)
assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS")
assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
-assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h;${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
+assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h4.h;${CMAKE_CURRENT_SOURCE_DIR}/h5.h")
assert_prop_eq(lib1 HEADER_DIRS_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}")
-assert_prop_eq(lib1 HEADER_SET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/h1.h;${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
+assert_prop_eq(lib1 HEADER_SET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/h4.h;${CMAKE_CURRENT_SOURCE_DIR}/h5.h")
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
diff --git a/Tests/RunCMake/target_sources/FileSetWrongType-stderr.txt b/Tests/RunCMake/target_sources/FileSetWrongType-stderr.txt
index 9cc764f..f87e393 100644
--- a/Tests/RunCMake/target_sources/FileSetWrongType-stderr.txt
+++ b/Tests/RunCMake/target_sources/FileSetWrongType-stderr.txt
@@ -1,4 +1,5 @@
^CMake Error at FileSetWrongType\.cmake:[0-9]+ \(target_sources\):
- target_sources File set TYPE may only be "HEADERS" or "CXX_MODULES"
+ target_sources File set TYPE may only be "HEADERS", "SOURCES",
+ "CXX_MODULES"
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
index 57e8b89..ff89e3c 100644
--- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
@@ -26,6 +26,7 @@
run_cmake(FileSetNoType)
run_cmake(FileSetWrongType)
run_cmake(FileSetDefaultWrongType)
+run_cmake(FileSetIncompatibleScopes)
run_cmake(FileSetChangeScope)
run_cmake(FileSetChangeType)
run_cmake(FileSetWrongBaseDirs)
@@ -43,9 +44,14 @@
run_cmake(FileSetBadName)
run_cmake(FileSetWrongSyntax)
run_cmake(FileSetDirect)
+run_cmake(FileSetDuplicateSource)
if(APPLE)
- run_cmake(FileSetFramework)
+ run_cmake(FileSetFramework1)
+ run_cmake(FileSetFramework2)
endif()
+run_cmake(CMP0211-OLD)
+run_cmake(CMP0211-NEW)
+run_cmake(CMP0211-WARN)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/FileSetGeneratedDependency-build")
diff --git a/Tests/RunCMake/target_sources/h4.h b/Tests/RunCMake/target_sources/h4.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/target_sources/h4.h
diff --git a/Tests/RunCMake/target_sources/h5.h b/Tests/RunCMake/target_sources/h5.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/target_sources/h5.h
diff --git a/Tests/RunCMake/test_include_dirs/TID-test-stdout.txt b/Tests/RunCMake/test_include_dirs/TID-test-stdout.txt
index 4810d8f..48d5489 100644
--- a/Tests/RunCMake/test_include_dirs/TID-test-stdout.txt
+++ b/Tests/RunCMake/test_include_dirs/TID-test-stdout.txt
@@ -12,6 +12,6 @@
Start 6: zoo\.emu
6/6 Test #6: zoo\.emu .+ +Passed +[0-9\.]+ sec
-100% tests passed, 0 tests failed out of 6
+100% tests passed out of 6
Total Test time \(real\) = +[0-9\.]+ sec
diff --git a/Tests/RunCMake/try_compile/ConfigureLog-config.txt b/Tests/RunCMake/try_compile/ConfigureLog-config.txt
index bd956df..6d1f82f 100644
--- a/Tests/RunCMake/try_compile/ConfigureLog-config.txt
+++ b/Tests/RunCMake/try_compile/ConfigureLog-config.txt
@@ -63,7 +63,7 @@
]*)+
buildResult:
variable: "CMAKE_C_FEATURE_TEST"
- cached: true
+ cached: false
stdout: \|.*
exitCode: 0)*
-
diff --git a/Tests/RunCMake/try_compile/CudaArchitectures-stderr.txt b/Tests/RunCMake/try_compile/CudaArchitectures-stderr.txt
new file mode 100644
index 0000000..76948bd
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CudaArchitectures-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Debug Log at [^
+]*/Modules/CMakeDetermineCompilerABI\.cmake:[0-9]+ \(try_compile\):
+ Executing try_compile \(CMAKE_C_ABI_COMPILED\) in:
+
+ [^
+]*/Tests/RunCMake/try_compile/CudaArchitectures-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/CMakeTestCCompiler\.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\)
+ CudaArchitectures\.cmake:[0-9]+ \(enable_language\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/try_compile/CudaArchitectures.cmake b/Tests/RunCMake/try_compile/CudaArchitectures.cmake
new file mode 100644
index 0000000..527c8f8
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CudaArchitectures.cmake
@@ -0,0 +1,19 @@
+enable_language(C)
+
+set(CMAKE_CUDA_ARCHITECTURES SOME_VALUE)
+
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
+
+# Check that the cache was populated with our custom variable.
+file(STRINGS ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeCache.txt entries
+ REGEX CMAKE_CUDA_ARCHITECTURES:UNINITIALIZED=${CMAKE_CUDA_ARCHITECTURES}
+ )
+if(NOT entries)
+ message(FATAL_ERROR "try_compile did not populate cache as expected")
+endif()
diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
index 3c684d2..07bf099 100644
--- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
@@ -52,7 +52,7 @@
set(RunCMake_TEST_OPTIONS --debug-trycompile)
run_cmake(PlatformVariables)
-run_cmake(WarnDeprecated)
+run_cmake(CudaArchitectures)
unset(RunCMake_TEST_OPTIONS)
if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
diff --git a/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt b/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt
deleted file mode 100644
index 2c6b62f..0000000
--- a/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-^CMake Debug Log at [^
-]*/Modules/CMakeDetermineCompilerABI\.cmake:[0-9]+ \(try_compile\):
- Executing try_compile \(CMAKE_C_ABI_COMPILED\) in:
-
- [^
-]*/Tests/RunCMake/try_compile/WarnDeprecated-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+
-Call Stack \(most recent call first\):
- [^
-]*/Modules/CMakeTestCCompiler\.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\)
- WarnDeprecated\.cmake:[0-9]+ \(enable_language\)
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/try_compile/WarnDeprecated.cmake b/Tests/RunCMake/try_compile/WarnDeprecated.cmake
deleted file mode 100644
index dfcb5f9..0000000
--- a/Tests/RunCMake/try_compile/WarnDeprecated.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-enable_language(C)
-
-set(CMAKE_WARN_DEPRECATED SOME_VALUE)
-
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
- OUTPUT_VARIABLE out
- )
-if(NOT result)
- message(FATAL_ERROR "try_compile failed:\n${out}")
-endif()
-
-# Check that the cache was populated with our custom variable.
-file(STRINGS ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeCache.txt entries
- REGEX CMAKE_WARN_DEPRECATED:UNINITIALIZED=${CMAKE_WARN_DEPRECATED}
- )
-if(NOT entries)
- message(FATAL_ERROR "try_compile did not populate cache as expected")
-endif()
diff --git a/Tests/RunCMake/try_run/ConfigureLog-config.txt b/Tests/RunCMake/try_run/ConfigureLog-config.txt
index eaa6b7b..c90e471 100644
--- a/Tests/RunCMake/try_run/ConfigureLog-config.txt
+++ b/Tests/RunCMake/try_run/ConfigureLog-config.txt
@@ -61,7 +61,7 @@
]*)+
buildResult:
variable: "CMAKE_C_FEATURE_TEST"
- cached: true
+ cached: false
stdout: \|.*
exitCode: 0)*
-
diff --git a/Tests/RustMix/CMakeLists.txt b/Tests/RustMix/CMakeLists.txt
index 8551afd..bf2f2c8 100644
--- a/Tests/RustMix/CMakeLists.txt
+++ b/Tests/RustMix/CMakeLists.txt
@@ -1,14 +1,30 @@
cmake_minimum_required(VERSION 4.2)
-set(CMAKE_EXPERIMENTAL_RUST "3cc9b32c-47d3-4056-8953-d74e69fc0d6c")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
-project(RustMix LANGUAGES C Rust)
+project(RustMix LANGUAGES C CXX Rust)
-add_library(liba STATIC liba.rs)
-add_library(libb SHARED libb.rs)
-add_library(libc OBJECT libc.rs)
+add_library(rs_staticlib STATIC rs_staticlib.rs)
+add_library(rs_cdylib SHARED rs_cdylib.rs)
+add_library(rs_rlib OBJECT rs_rlib.rs)
-add_executable(RustMix main.c)
-target_link_libraries(RustMix liba)
-target_link_libraries(RustMix libb)
-target_link_libraries(RustMix libc)
+add_library(c_static STATIC c_static.c)
+add_library(c_shared SHARED c_shared.c)
+add_library(c_obj OBJECT c_obj.c)
+
+add_library(cpp_shared SHARED cpp_shared.cpp)
+# Note: trying to link a C++ object file or static library into the Rust
+# executable currently fails with errors related to missing symbols from
+# libstdc++, while libstdc++ is present on the linker command line.
+
+add_executable(RustMix main.rs)
+target_link_libraries(
+ RustMix
+ rs_staticlib
+ rs_cdylib
+ rs_rlib
+ c_static
+ c_shared
+ c_obj
+ cpp_shared
+)
diff --git a/Tests/RustMix/c_obj.c b/Tests/RustMix/c_obj.c
new file mode 100644
index 0000000..e269d41
--- /dev/null
+++ b/Tests/RustMix/c_obj.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void c_obj_greet()
+{
+ printf("Hello from a C object file!");
+}
diff --git a/Tests/RustMix/c_shared.c b/Tests/RustMix/c_shared.c
new file mode 100644
index 0000000..42255a3
--- /dev/null
+++ b/Tests/RustMix/c_shared.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void c_shared_greet()
+{
+ printf("Hello from a C shared library!");
+}
diff --git a/Tests/RustMix/c_static.c b/Tests/RustMix/c_static.c
new file mode 100644
index 0000000..6af1de2
--- /dev/null
+++ b/Tests/RustMix/c_static.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void c_static_greet()
+{
+ printf("Hello from a C static library!");
+}
diff --git a/Tests/RustMix/cpp_shared.cpp b/Tests/RustMix/cpp_shared.cpp
new file mode 100644
index 0000000..bee6784
--- /dev/null
+++ b/Tests/RustMix/cpp_shared.cpp
@@ -0,0 +1,6 @@
+#include <iostream>
+
+extern "C" void cpp_shared_greet()
+{
+ std::cout << "Hello from a C++ shader library" << std::endl;
+}
diff --git a/Tests/RustMix/liba.rs b/Tests/RustMix/liba.rs
deleted file mode 100644
index 2958db3..0000000
--- a/Tests/RustMix/liba.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[no_mangle]
-pub extern "C" fn liba_greet() {
- println!("Hello from Rust liba");
-}
diff --git a/Tests/RustMix/libb.rs b/Tests/RustMix/libb.rs
deleted file mode 100644
index e94f46f..0000000
--- a/Tests/RustMix/libb.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[no_mangle]
-pub extern "C" fn libb_greet() {
- println!("Hello from Rust libb");
-}
diff --git a/Tests/RustMix/libc.rs b/Tests/RustMix/libc.rs
deleted file mode 100644
index 52bd67d..0000000
--- a/Tests/RustMix/libc.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[no_mangle]
-pub extern "C" fn libc_greet() {
- println!("Hello from Rust libc");
-}
diff --git a/Tests/RustMix/main.c b/Tests/RustMix/main.c
deleted file mode 100644
index 39ceba1..0000000
--- a/Tests/RustMix/main.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-extern void liba_greet();
-extern void libb_greet();
-extern void libc_greet();
-
-int main()
-{
- printf("Hello from C main\n");
- liba_greet();
- libb_greet();
- libc_greet();
-
- return 0;
-}
diff --git a/Tests/RustMix/main.rs b/Tests/RustMix/main.rs
new file mode 100644
index 0000000..fc153b0
--- /dev/null
+++ b/Tests/RustMix/main.rs
@@ -0,0 +1,30 @@
+extern "C" {
+ // Functions defined in C
+ fn c_obj_greet();
+ fn c_static_greet();
+ fn c_shared_greet();
+
+ // Functions defined in C++
+ fn cpp_shared_greet();
+
+ // Functions defined in Rust through a C-style ABI
+ fn rs_staticlib_greet();
+ fn rs_cdylib_greet();
+}
+
+// Functions defined in Rust, using native Rust ABI
+extern crate rs_rlib;
+use rs_rlib::rs_rlib_greet;
+
+fn main() {
+ println!("Hello from main.rs");
+ unsafe {
+ c_obj_greet();
+ c_static_greet();
+ c_shared_greet();
+ cpp_shared_greet();
+ rs_staticlib_greet();
+ rs_cdylib_greet();
+ }
+ rs_rlib_greet();
+}
diff --git a/Tests/RustMix/rs_cdylib.rs b/Tests/RustMix/rs_cdylib.rs
new file mode 100644
index 0000000..ff8fd29
--- /dev/null
+++ b/Tests/RustMix/rs_cdylib.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn rs_cdylib_greet() {
+ println!("Hello from a Rust cdylib!");
+}
diff --git a/Tests/RustMix/rs_rlib.rs b/Tests/RustMix/rs_rlib.rs
new file mode 100644
index 0000000..6456453
--- /dev/null
+++ b/Tests/RustMix/rs_rlib.rs
@@ -0,0 +1,3 @@
+pub fn rs_rlib_greet() {
+ println!("Hello from a Rust rlib!");
+}
diff --git a/Tests/RustMix/rs_staticlib.rs b/Tests/RustMix/rs_staticlib.rs
new file mode 100644
index 0000000..c25b65f
--- /dev/null
+++ b/Tests/RustMix/rs_staticlib.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn rs_staticlib_greet() {
+ println!("Hello from a Rust staticlib!");
+}
diff --git a/Tests/RustOnly/CMakeLists.txt b/Tests/RustOnly/CMakeLists.txt
index 8f889fb..29b4a5b 100644
--- a/Tests/RustOnly/CMakeLists.txt
+++ b/Tests/RustOnly/CMakeLists.txt
@@ -1,14 +1,18 @@
cmake_minimum_required(VERSION 4.2)
-set(CMAKE_EXPERIMENTAL_RUST "3cc9b32c-47d3-4056-8953-d74e69fc0d6c")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
project(RustOnly LANGUAGES Rust)
-add_library(liba STATIC liba.rs)
-add_library(libb SHARED libb.rs)
-add_library(libc OBJECT libc.rs)
+add_library(a STATIC a.rs)
+add_library(b SHARED b.rs)
+add_library(c OBJECT c.rs)
-add_executable(RustOnly main.rs)
-target_link_libraries(RustOnly liba)
-target_link_libraries(RustOnly libb)
-target_link_libraries(RustOnly libc)
+add_executable(RustOnly d.rs main.rs e.rs)
+# Ensure that Rust_MAIN_CRATE_ROOT property works.
+set_target_properties(RustOnly PROPERTIES Rust_MAIN_CRATE_ROOT main.rs)
+# Emit an object file instead of an rlib.
+set_source_files_properties(e.rs PROPERTIES Rust_EMIT "obj")
+target_link_libraries(RustOnly a)
+target_link_libraries(RustOnly b)
+target_link_libraries(RustOnly c)
diff --git a/Tests/RustOnly/liba.rs b/Tests/RustOnly/a.rs
similarity index 100%
rename from Tests/RustOnly/liba.rs
rename to Tests/RustOnly/a.rs
diff --git a/Tests/RustOnly/libb.rs b/Tests/RustOnly/b.rs
similarity index 100%
rename from Tests/RustOnly/libb.rs
rename to Tests/RustOnly/b.rs
diff --git a/Tests/RustOnly/c.rs b/Tests/RustOnly/c.rs
new file mode 100644
index 0000000..6de15d7
--- /dev/null
+++ b/Tests/RustOnly/c.rs
@@ -0,0 +1,4 @@
+// We can expose a Rust API, as this is compiled into a rlib.
+pub fn libc_greet() {
+ println!("Hello from libc");
+}
diff --git a/Tests/RustOnly/d.rs b/Tests/RustOnly/d.rs
new file mode 100644
index 0000000..52de74c
--- /dev/null
+++ b/Tests/RustOnly/d.rs
@@ -0,0 +1,4 @@
+// We can expose a Rust API, as this is compiled into a rlib.
+pub fn libd_greet() {
+ println!("Hello from libd");
+}
diff --git a/Tests/RustOnly/e.rs b/Tests/RustOnly/e.rs
new file mode 100644
index 0000000..4b3bd74
--- /dev/null
+++ b/Tests/RustOnly/e.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn libe_greet() {
+ println!("Hello from libe");
+}
diff --git a/Tests/RustOnly/libc.rs b/Tests/RustOnly/libc.rs
deleted file mode 100644
index dd46cc5..0000000
--- a/Tests/RustOnly/libc.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[no_mangle]
-pub extern "C" fn libc_greet() {
- println!("Hello from libc");
-}
diff --git a/Tests/RustOnly/main.rs b/Tests/RustOnly/main.rs
index 067fb24..af91fc3 100644
--- a/Tests/RustOnly/main.rs
+++ b/Tests/RustOnly/main.rs
@@ -3,13 +3,20 @@
extern "C" {
fn liba_greet();
fn libb_greet();
- fn libc_greet();
+ fn libe_greet();
}
+extern crate c;
+extern crate d;
+use c::libc_greet;
+use d::libd_greet;
+
fn main() {
println!("Hello from main.rs");
moda::moda_greet();
unsafe { liba_greet() };
unsafe { libb_greet() };
- unsafe { libc_greet() };
+ libc_greet();
+ libd_greet();
+ unsafe { libe_greet() };
}
diff --git a/Tests/RustPie/CMakeLists.txt b/Tests/RustPie/CMakeLists.txt
new file mode 100644
index 0000000..0c3b657
--- /dev/null
+++ b/Tests/RustPie/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 4.2)
+
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
+
+function(setup PREFIX)
+ add_library(${PREFIX}_static STATIC ../static.rs)
+ add_library(${PREFIX}_shared SHARED ../shared.rs)
+ add_library(${PREFIX}_object OBJECT ../object.rs)
+
+ add_executable(${PREFIX}_RustPie ../main.rs)
+ target_link_libraries(
+ ${PREFIX}_RustPie PRIVATE
+ ${PREFIX}_static
+ ${PREFIX}_shared
+ ${PREFIX}_object
+ )
+endfunction()
+
+project(RustPie LANGUAGES Rust)
+
+add_subdirectory(Default)
+add_subdirectory(Disabled)
+add_subdirectory(Enabled)
+
+file(
+ GENERATE OUTPUT ${CMAKE_BINARY_DIR}/runner_$<CONFIG>.rs
+ INPUT runner.rs
+)
+
+add_executable(RustPie ${CMAKE_BINARY_DIR}/runner_$<CONFIG>.rs)
+add_dependencies(RustPie default_RustPie disabled_RustPie enabled_RustPie)
diff --git a/Tests/RustPie/Default/CMakeLists.txt b/Tests/RustPie/Default/CMakeLists.txt
new file mode 100644
index 0000000..806bd62
--- /dev/null
+++ b/Tests/RustPie/Default/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+project(DefaultRustPie LANGUAGES Rust)
+setup(default)
diff --git a/Tests/RustPie/Disabled/CMakeLists.txt b/Tests/RustPie/Disabled/CMakeLists.txt
new file mode 100644
index 0000000..b5161be
--- /dev/null
+++ b/Tests/RustPie/Disabled/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+project(DisabledRustPie LANGUAGES Rust)
+setup(disabled)
+
+set_property(
+ TARGET
+ disabled_static
+ disabled_shared
+ disabled_object
+ disabled_RustPie
+ PROPERTY POSITION_INDEPENDENT_CODE OFF
+)
diff --git a/Tests/RustPie/Enabled/CMakeLists.txt b/Tests/RustPie/Enabled/CMakeLists.txt
new file mode 100644
index 0000000..c48a4e3
--- /dev/null
+++ b/Tests/RustPie/Enabled/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+project(EnabledRustPie LANGUAGES Rust)
+setup(enabled)
+
+set_property(
+ TARGET
+ enabled_static
+ enabled_shared
+ enabled_object
+ enabled_RustPie
+ PROPERTY POSITION_INDEPENDENT_CODE TRUE
+)
diff --git a/Tests/RustPie/main.rs b/Tests/RustPie/main.rs
new file mode 100644
index 0000000..fb92a96
--- /dev/null
+++ b/Tests/RustPie/main.rs
@@ -0,0 +1,18 @@
+
+extern "C" {
+ fn static_foo();
+ fn shared_foo();
+}
+
+
+extern crate object;
+use object::object_foo;
+
+
+fn main() {
+ unsafe {
+ static_foo();
+ shared_foo();
+ }
+ object_foo();
+}
diff --git a/Tests/RustPie/object.rs b/Tests/RustPie/object.rs
new file mode 100644
index 0000000..b189f46
--- /dev/null
+++ b/Tests/RustPie/object.rs
@@ -0,0 +1,3 @@
+pub fn object_foo() {
+ println!("object_foo");
+}
diff --git a/Tests/RustPie/runner.rs b/Tests/RustPie/runner.rs
new file mode 100644
index 0000000..bc0a798
--- /dev/null
+++ b/Tests/RustPie/runner.rs
@@ -0,0 +1,66 @@
+
+use std::process::Command;
+
+#[cfg(target_os="macos")]
+fn is_pie_executable(executable: &str) -> bool {
+ let output = Command::new("otool")
+ .args(["-hv", executable])
+ .output()
+ .expect("Failed to check executable");
+ if !output.status.success() {
+ panic!("otool exited with non-zero exit code");
+ }
+
+ output.stdout.windows(5).any(|w| {
+ (w[0] == b' ' || w[0] == b'\t')
+ && (w[1..=3] == b"PIE")
+ && (w[4] == b' ' || w[4] == b'\n')
+ })
+}
+
+#[cfg(all(target_family="unix", not(target_os="macos")))]
+fn is_pie_executable(executable: &str) -> bool {
+ let output = Command::new("readelf")
+ .args(["-lW", executable])
+ .env("LANG", "C")
+ .env("LC_ALL", "C")
+ .output()
+ .expect("Failed to check executable");
+ if !output.status.success() {
+ panic!("readelf exited with non-zero exit code");
+ }
+ let is_pie = output.stdout.windows(20).any(|w| w == b"Elf file type is DYN");
+ let is_not_pie = output.stdout.windows(21).any(|w| w == b"Elf file type is EXEC");
+ assert!(is_pie ^ is_not_pie, "Cannot determine type of ELF file");
+ is_pie
+}
+
+fn main() {
+ let commands = [
+ // The actual path to the commands will be filled in by CMake.
+ r#"$<TARGET_FILE:default_RustPie>"#,
+ r#"$<TARGET_FILE:disabled_RustPie>"#,
+ r#"$<TARGET_FILE:enabled_RustPie>"#,
+ ];
+ for command in commands {
+ println!("Start command: {command:?}");
+ let result = Command::new(command)
+ .spawn()
+ .expect("Failed to launch command")
+ .wait()
+ .expect("Failure while waiting for process to finish")
+ .success();
+ if !result {
+ panic!("Process exited with non-zero exit code.");
+ }
+ }
+
+ assert!(
+ !is_pie_executable(commands[1]),
+ "ERROR: disabled_RustPie must not be a PIE executable, but it is not."
+ );
+ assert!(
+ is_pie_executable(commands[2]),
+ "ERROR: enabled_RustPie must be a PIE executable, but it is not."
+ );
+}
diff --git a/Tests/RustPie/shared.rs b/Tests/RustPie/shared.rs
new file mode 100644
index 0000000..40f89e6
--- /dev/null
+++ b/Tests/RustPie/shared.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn shared_foo() {
+ println!("shared_foo");
+}
diff --git a/Tests/RustPie/static.rs b/Tests/RustPie/static.rs
new file mode 100644
index 0000000..99b3116
--- /dev/null
+++ b/Tests/RustPie/static.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn static_foo() {
+ println!("static_foo");
+}
diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt
index be6154c..55e924e 100644
--- a/Tests/VSResource/CMakeLists.txt
+++ b/Tests/VSResource/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
-project(VSResource)
+project(VSResource LANGUAGES C)
string(REPLACE "/INCREMENTAL:YES" ""
CMAKE_EXE_LINKER_FLAGS_DEBUG
@@ -45,9 +45,9 @@
include_directories(${CMAKE_CURRENT_BINARY_DIR})
endif()
-add_library(ResourceLib STATIC lib.cpp lib.rc)
+add_library(ResourceLib STATIC lib.c lib.rc)
-add_executable(VSResource main.cpp test.rc)
+add_executable(VSResource main.c test.rc)
target_link_libraries(VSResource ResourceLib)
if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600)
diff --git a/Tests/VSResource/lib.c b/Tests/VSResource/lib.c
new file mode 100644
index 0000000..abe3b78
--- /dev/null
+++ b/Tests/VSResource/lib.c
@@ -0,0 +1,4 @@
+int lib(void)
+{
+ return 0;
+}
diff --git a/Tests/VSResource/lib.cpp b/Tests/VSResource/lib.cpp
deleted file mode 100644
index c912397..0000000
--- a/Tests/VSResource/lib.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-int lib()
-{
- return 0;
-}
diff --git a/Tests/VSResource/main.c b/Tests/VSResource/main.c
new file mode 100644
index 0000000..68078d1
--- /dev/null
+++ b/Tests/VSResource/main.c
@@ -0,0 +1,80 @@
+#include <windows.h>
+
+#include <stdio.h>
+
+extern int lib(void);
+
+struct x
+{
+ char const* txt;
+};
+
+int main(int argc, char** argv)
+{
+ int ret = 1;
+ HRSRC hello = FindResource(NULL, MAKEINTRESOURCE(1025), "TEXTFILE");
+
+ fprintf(stdout, "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)\n");
+
+#ifdef CMAKE_RCDEFINE
+ fprintf(stdout, "CMAKE_RCDEFINE defined\n");
+#endif
+
+#ifdef CMAKE_RCDEFINE_NO_QUOTED_STRINGS
+ {
+ // Expect CMAKE_RCDEFINE to preprocess to exactly test.txt
+ struct x test;
+ test.txt = "*exactly* test.txt";
+ fprintf(stdout, "CMAKE_RCDEFINE_NO_QUOTED_STRINGS defined\n");
+ fprintf(stdout, "CMAKE_RCDEFINE is %s, and is *not* a string constant\n",
+ CMAKE_RCDEFINE);
+ }
+#else
+ // Expect CMAKE_RCDEFINE to be a string:
+ fprintf(stdout, "CMAKE_RCDEFINE='%s', and is a string constant\n",
+ CMAKE_RCDEFINE);
+#endif
+
+ if (hello) {
+ HGLOBAL hgbl = LoadResource(NULL, hello);
+ int datasize = (int)SizeofResource(NULL, hello);
+ fprintf(stdout, "FindResource worked\n");
+ if (hgbl && datasize > 0) {
+ void* data = LockResource(hgbl);
+ fprintf(stdout, "LoadResource worked\n");
+ fprintf(stdout, "SizeofResource returned datasize='%d'\n", datasize);
+ if (data) {
+ char* str = (char*)malloc(datasize + 4);
+ fprintf(stdout, "LockResource worked\n");
+ if (str) {
+ memcpy(str, data, datasize);
+ str[datasize] = 'E';
+ str[datasize + 1] = 'O';
+ str[datasize + 2] = 'R';
+ str[datasize + 3] = 0;
+ fprintf(stdout, "str='%s'\n", str);
+ free(str);
+
+ ret = 0;
+
+#ifdef CMAKE_RCDEFINE_NO_QUOTED_STRINGS
+ fprintf(stdout, "LoadString skipped\n");
+#else
+ {
+ char buf[256];
+ if (LoadString(NULL, 1026, buf, sizeof(buf)) > 0) {
+ fprintf(stdout, "LoadString worked\n");
+ fprintf(stdout, "buf='%s'\n", buf);
+ } else {
+ fprintf(stdout, "LoadString failed\n");
+ ret = 1;
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+
+ return ret + lib();
+}
diff --git a/Tests/VSResource/main.cpp b/Tests/VSResource/main.cpp
deleted file mode 100644
index 65e33b8..0000000
--- a/Tests/VSResource/main.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <windows.h>
-
-#include <stdio.h>
-
-extern int lib();
-
-struct x
-{
- char const* txt;
-};
-
-int main(int argc, char** argv)
-{
- int ret = 1;
-
- fprintf(stdout, "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)\n");
-
-#ifdef CMAKE_RCDEFINE
- fprintf(stdout, "CMAKE_RCDEFINE defined\n");
-#endif
-
-#ifdef CMAKE_RCDEFINE_NO_QUOTED_STRINGS
- // Expect CMAKE_RCDEFINE to preprocess to exactly test.txt
- x test;
- test.txt = "*exactly* test.txt";
- fprintf(stdout, "CMAKE_RCDEFINE_NO_QUOTED_STRINGS defined\n");
- fprintf(stdout, "CMAKE_RCDEFINE is %s, and is *not* a string constant\n",
- CMAKE_RCDEFINE);
-#else
- // Expect CMAKE_RCDEFINE to be a string:
- fprintf(stdout, "CMAKE_RCDEFINE='%s', and is a string constant\n",
- CMAKE_RCDEFINE);
-#endif
-
- HRSRC hello = ::FindResource(NULL, MAKEINTRESOURCE(1025), "TEXTFILE");
- if (hello) {
- fprintf(stdout, "FindResource worked\n");
- HGLOBAL hgbl = ::LoadResource(NULL, hello);
- int datasize = (int)::SizeofResource(NULL, hello);
- if (hgbl && datasize > 0) {
- fprintf(stdout, "LoadResource worked\n");
- fprintf(stdout, "SizeofResource returned datasize='%d'\n", datasize);
- void* data = ::LockResource(hgbl);
- if (data) {
- fprintf(stdout, "LockResource worked\n");
- char* str = (char*)malloc(datasize + 4);
- if (str) {
- memcpy(str, data, datasize);
- str[datasize] = 'E';
- str[datasize + 1] = 'O';
- str[datasize + 2] = 'R';
- str[datasize + 3] = 0;
- fprintf(stdout, "str='%s'\n", str);
- free(str);
-
- ret = 0;
-
-#ifdef CMAKE_RCDEFINE_NO_QUOTED_STRINGS
- fprintf(stdout, "LoadString skipped\n");
-#else
- char buf[256];
- if (::LoadString(NULL, 1026, buf, sizeof(buf)) > 0) {
- fprintf(stdout, "LoadString worked\n");
- fprintf(stdout, "buf='%s'\n", buf);
- } else {
- fprintf(stdout, "LoadString failed\n");
- ret = 1;
- }
-#endif
- }
- }
- }
- }
-
- return ret + lib();
-}
diff --git a/Tests/VSResourceNinjaForceRSP/CMakeLists.txt b/Tests/VSResourceNinjaForceRSP/CMakeLists.txt
index d9d0bd0..909e0be 100644
--- a/Tests/VSResourceNinjaForceRSP/CMakeLists.txt
+++ b/Tests/VSResourceNinjaForceRSP/CMakeLists.txt
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.10)
-project(VSResourceNinjaForceRSP)
+project(VSResourceNinjaForceRSP LANGUAGES C)
set(CMAKE_NINJA_FORCE_RESPONSE_FILE TRUE)
-add_library(ResourceLib lib.cpp test.rc)
-add_executable(VSResourceNinjaForceRSP main.cpp test.rc)
+add_library(ResourceLib lib.c test.rc)
+add_executable(VSResourceNinjaForceRSP main.c test.rc)
diff --git a/Tests/VSResourceNinjaForceRSP/lib.c b/Tests/VSResourceNinjaForceRSP/lib.c
new file mode 100644
index 0000000..abe3b78
--- /dev/null
+++ b/Tests/VSResourceNinjaForceRSP/lib.c
@@ -0,0 +1,4 @@
+int lib(void)
+{
+ return 0;
+}
diff --git a/Tests/VSResourceNinjaForceRSP/lib.cpp b/Tests/VSResourceNinjaForceRSP/lib.cpp
deleted file mode 100644
index c912397..0000000
--- a/Tests/VSResourceNinjaForceRSP/lib.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-int lib()
-{
- return 0;
-}
diff --git a/Tests/VSResourceNinjaForceRSP/main.cpp b/Tests/VSResourceNinjaForceRSP/main.c
similarity index 100%
rename from Tests/VSResourceNinjaForceRSP/main.cpp
rename to Tests/VSResourceNinjaForceRSP/main.c
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index e760924..0d29b1c 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeDeveloperReference_STANDALONE 1)
- cmake_minimum_required(VERSION 3.13...4.1 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.13...4.2 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index a613bce..91f3014 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -54,6 +54,10 @@
{ symbol: [ "S_IWUSR", private, "\"cm_sys_stat.h\"", public ] },
{ symbol: [ "S_IWGRP", private, "\"cm_sys_stat.h\"", public ] },
+ { symbol: [ "std::filesystem::path", private, "<cm/filesystem>", public ] },
+ { symbol: [ "std::optional", private, "<cm/optional>", public ] },
+ { symbol: [ "std::string_view", private, "<cm/string_view>", public ] },
+
{ include: [ "<filesystem>", public, "<cm/filesystem>", public ] },
{ include: [ "<optional>", public, "<cm/optional>", public ] },
{ include: [ "<shared_mutex>", public, "<cm/shared_mutex>", public ] },
diff --git a/Utilities/KWIML/include/kwiml/abi.h b/Utilities/KWIML/include/kwiml/abi.h
index 9b23580..d979ce7 100644
--- a/Utilities/KWIML/include/kwiml/abi.h
+++ b/Utilities/KWIML/include/kwiml/abi.h
@@ -155,7 +155,7 @@
#if !defined(KWIML_ABI_CHAR_IS_UNSIGNED) && !defined(KWIML_ABI_CHAR_IS_SIGNED)
# if defined(__CHAR_UNSIGNED__) /* GNU, some IBM XL, others? */
# define KWIML_ABI_CHAR_IS_UNSIGNED 1
-# elif defined(_CHAR_UNSIGNED) /* Intel, IBM XL, MSVC, Borland, others? */
+# elif defined(_CHAR_UNSIGNED) /* Intel, IBM XL, MSVC, Borland, Pelles C, others? */
# define KWIML_ABI_CHAR_IS_UNSIGNED 1
# elif defined(_CHAR_SIGNED) /* IBM XL, others? */
# define KWIML_ABI_CHAR_IS_SIGNED 1
@@ -177,6 +177,8 @@
# define KWIML_ABI_CHAR_IS_UNSIGNED 1
# elif defined(__PGIC__) /* PGI default */
# define KWIML_ABI_CHAR_IS_SIGNED 1
+# elif defined(__POCC__) /* PellesC default */
+# define KWIML_ABI_CHAR_IS_SIGNED 1
# elif defined(_MSC_VER) /* MSVC default */
# define KWIML_ABI_CHAR_IS_SIGNED 1
# elif defined(__WATCOMC__) /* Watcom default */
diff --git a/Utilities/Scripts/regenerate-presets.py b/Utilities/Scripts/regenerate-presets.py
new file mode 100755
index 0000000..ccb5bab
--- /dev/null
+++ b/Utilities/Scripts/regenerate-presets.py
@@ -0,0 +1,686 @@
+#!/usr/bin/env python3
+"""Generate CMake presets documentation (reST) and JSON schema.
+
+The documentation and JSON schema for CMake presets are both generated from
+Help/manual/presets/schema.yaml, which describes the schema in a way that
+allows both documentation forms to be combined in a single file, and also makes
+it much easier to manage version revisions (compared to editing the JSON schema
+'by hand').
+
+All input and output files are expected to be in known locations relative to
+this script.
+
+Usage: python3 regenerate-presets.py
+"""
+
+import json
+from copy import deepcopy
+from pathlib import Path
+from typing import Any, Self
+
+import yaml
+
+LATEST = 1
+TYPES = {}
+REFS = {}
+
+PRESETS_REL = 'Help/manual/presets'
+SCHEMA_YAML_FILENAME = 'schema.yaml'
+SCHEMA_JSON_FILENAME = 'schema.json'
+
+WORKSPACE = Path(__file__).parent.parent.parent.absolute()
+PRESETS = WORKSPACE / PRESETS_REL
+
+RST_BANNER = f"""\
+.. This file was generated by {Path(__file__).relative_to(WORKSPACE)}
+ from {PRESETS_REL}/{SCHEMA_YAML_FILENAME}. Do not edit.
+"""
+
+
+# =============================================================================
+class Value:
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: list[dict[str, Any]]):
+ self.data = data
+ self.spans = None
+
+ # -------------------------------------------------------------------------
+ @property
+ def objects(self) -> dict[str, 'Object']:
+ return {}
+
+ # -------------------------------------------------------------------------
+ def updateSpans(self, since: int, until: int) -> None:
+ self.spans = [(since, until)]
+
+ # -------------------------------------------------------------------------
+ def updateRefs(self, objects: dict[str, 'Object']) -> None:
+ pass
+
+ # -------------------------------------------------------------------------
+ def defs(self) -> dict[str, Any]:
+ return {}
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int) -> dict[str, Any]:
+ return deepcopy(self.data)
+
+
+# =============================================================================
+class Object(Value):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: dict[str, Any], name: str,
+ label: str | None = None):
+ # Prevent data sharing from modifying unrelated parts of the schema as
+ # we pick apart our section.
+ data = deepcopy(data)
+
+ self.name = data.pop('id', name)
+ self.label = label
+
+ self.properties = {}
+ for n, p in data.pop('properties').items():
+ pl = '.'.join([label, n]) if label is not None else n
+ self.properties[n] = Property(p, n, pl)
+ if len(self.properties):
+ self.properties[CommentProperty.name] = CommentProperty()
+
+ ap = data.pop('additionalProperties', None)
+ if ap is not None:
+ self.additionalProperties = buildValue(ap, self.name, self.label)
+ else:
+ self.additionalProperties = None
+
+ super().__init__(data)
+
+ # -------------------------------------------------------------------------
+ @property
+ def objects(self) -> dict[str, Self]:
+ out = {self.name: self}
+ for p in self.properties.values():
+ out.update(p.objects)
+ if self.additionalProperties is not None:
+ out.update(self.additionalProperties.objects)
+ return out
+
+ # -------------------------------------------------------------------------
+ def updateSpans(self, since: int, until: int) -> None:
+ spans = [[(since, until)]]
+ for p in self.properties.values():
+ p.updateSpans(since, until)
+ spans.append(p.spans)
+ if self.additionalProperties is not None:
+ self.additionalProperties.updateSpans(since, until)
+ spans.append(self.additionalProperties.spans)
+ self.spans = combineSpans(*spans)
+
+ # -------------------------------------------------------------------------
+ def updateRefs(self, objects: dict[str, 'Object']) -> None:
+ for p in self.properties.values():
+ p.updateRefs(objects)
+ if self.additionalProperties is not None:
+ self.additionalProperties.updateRefs(objects)
+
+ # -------------------------------------------------------------------------
+ def doc(self, since: int, until: int) -> str | None:
+ since = max(since, self.spans[0][0])
+ until = min(until, self.spans[-1][1])
+
+ out = []
+ for _, p in self.properties.items():
+ content = p.doc(since, until)
+ if not content:
+ continue
+ out.append(content)
+
+ return '\n\n'.join(out) if len(out) else None
+
+ # -------------------------------------------------------------------------
+ def defs(self, exclude: set[str] = {}) -> dict[str, Any]:
+ out = {}
+ for n, p in self.properties.items():
+ if n in exclude:
+ continue
+ for s in p.spans:
+ r = f'{p.label}@{spanRef(*s)}'
+ out[r] = p.schema(s[0])
+ out.update(p.defs())
+ if self.additionalProperties is not None:
+ out.update(self.additionalProperties.defs())
+ return out
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int, inline: set[str] = {}) -> dict[str, Any]:
+ out = deepcopy(self.data)
+
+ props = {}
+ required = []
+ for n, p in self.properties.items():
+ if n in inline:
+ props[n] = p.schema(version)
+ else:
+ r = p.ref(version)
+ if r is not None:
+ props[n] = r
+ if p.required:
+ required.append(n)
+
+ out['properties'] = props
+ if len(required):
+ out['required'] = required
+
+ if self.additionalProperties is not None:
+ ap = self.additionalProperties.schema(version)
+ out['additionalProperties'] = ap
+ return out
+
+
+# =============================================================================
+class Ref(Value):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: list[dict[str, Any]]):
+ self.target = data.pop('target')
+ self.targetSpans = None
+ super().__init__(data)
+
+ # -------------------------------------------------------------------------
+ def updateSpans(self, since: int, until: int) -> None:
+ if self.spans is None:
+ super().updateSpans(since, until)
+ self.spans = trimSpans(self.spans, since, until)
+
+ # -------------------------------------------------------------------------
+ def updateRefs(self, objects: dict[str, 'Object']) -> None:
+ global REFS
+
+ t = objects.get(self.target)
+ if t is not None:
+ since = self.spans[0][0]
+ until = self.spans[-1][1]
+ self.spans = trimSpans(t.spans, since, until)
+ self.targetSpans = t.spans
+
+ rs = REFS.get(self.target, (since, until))
+ REFS[self.target] = (min(since, rs[0]), max(until, rs[1]))
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int) -> dict[str, Any]:
+ ts = trimSpans(self.targetSpans, *REFS[self.target])
+ s = findSpan(ts, version)
+ if s is not None:
+ return {
+ '$ref': f'#/definitions/{self.target}@{spanRef(*s)}',
+ }
+ return {}
+
+
+# =============================================================================
+class Array(Value):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: dict[str, Any], name: str, label: str):
+ item = data.pop('items')
+ self.value = buildValue(item, name, label)
+
+ super().__init__(data)
+
+ # -------------------------------------------------------------------------
+ @property
+ def objects(self) -> dict[str, Object]:
+ return self.value.objects
+
+ # -------------------------------------------------------------------------
+ def updateSpans(self, since: int, until: int) -> None:
+ self.value.updateSpans(since, until)
+ self.spans = self.value.spans
+
+ # -------------------------------------------------------------------------
+ def updateRefs(self, objects: dict[str, 'Object']) -> None:
+ self.value.updateRefs(objects)
+
+ # -------------------------------------------------------------------------
+ def defs(self) -> dict[str, Any]:
+ return self.value.defs()
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int) -> dict[str, Any]:
+ out = deepcopy(self.data)
+ out['items'] = self.value.schema(version)
+ return out
+
+
+# =============================================================================
+class Union(Value):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: list[dict[str, Any]], name: str, label: str):
+ self.items = []
+ for i, d in enumerate(data):
+ self.items.append(buildValue(d, name, self.itemLabel(label, i)))
+
+ super().__init__({})
+
+ # -------------------------------------------------------------------------
+ def itemLabel(self, label: str, index: int) -> str:
+ return label
+
+ # -------------------------------------------------------------------------
+ @property
+ def objects(self) -> dict[str, Object]:
+ out = {}
+ for v in self.items:
+ out.update(v.objects)
+ return out
+
+ # -------------------------------------------------------------------------
+ def updateSpans(self, since: int, until: int) -> None:
+ spans = [[(since, until)]]
+ for i in self.items:
+ i.updateSpans(since, until)
+ spans.append(i.spans)
+ self.spans = combineSpans(*spans)
+
+ # -------------------------------------------------------------------------
+ def updateRefs(self, objects: dict[str, 'Object']) -> None:
+ for i in self.items:
+ i.updateRefs(objects)
+
+ # -------------------------------------------------------------------------
+ def defs(self) -> dict[str, Any]:
+ out = {}
+ for v in self.items:
+ out.update(v.defs())
+ return out
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int) -> dict[str, Any]:
+ out = []
+ for i in self.items:
+ out.append(i.schema(version))
+ return {'anyOf': out}
+
+
+# =============================================================================
+class Variant(Union):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: list[dict[str, Any]], name: str, label: str):
+ self.identifier = data.pop('id', None)
+
+ if self.identifier is not None:
+ name = self.identifier
+ label = self.identifier
+
+ super().__init__(data.pop('items'), name, label)
+
+ # -------------------------------------------------------------------------
+ def itemLabel(self, label: str, index: int) -> str:
+ return f'{label}[{index}]'
+
+ # -------------------------------------------------------------------------
+ @property
+ def objects(self) -> dict[str, Object]:
+ out = super().objects
+ if self.identifier is not None:
+ out[self.identifier] = self
+ return out
+
+ # -------------------------------------------------------------------------
+ def doc(self, since: int, until: int) -> None:
+ return None
+
+ # -------------------------------------------------------------------------
+ def defs(self) -> dict[str, Any]:
+ out = super().defs()
+
+ if self.identifier is not None:
+ for s in self.spans:
+ n = f'{self.identifier}@{spanRef(*s)}'
+ out[n] = super().schema(s[0])
+
+ return out
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int) -> dict[str, Any]:
+ if self.identifier is not None:
+ s = findSpan(self.spans, version)
+ if s is not None:
+ return {
+ '$ref': f'#/definitions/{self.identifier}@{spanRef(*s)}',
+ }
+ return {}
+
+ return super().schema(version)
+
+
+# =============================================================================
+class Property:
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data: dict[str, Any], name: str, label: str):
+ self.name = name
+ self.label = label
+ self.since = data.pop('since', 1)
+ self.until = data.pop('until', LATEST + 1)
+ self.required = data.pop('required', False)
+ self.content = data.pop('sphinxDescription', data.get('description'))
+
+ note = data.pop('sphinxNote', None)
+ if note is not None:
+ self.content += f'\n\n.. note::\n\n{indent(note)}'
+
+ self._revisions = []
+ for rev in data.pop('revisions', []):
+ rd = deepcopy(data)
+ rd.update(rev)
+ self._revisions.append(Property(rd, self.name, self.label))
+
+ if len(self._revisions):
+ self.since = max(self.since,
+ min([r.since for r in self._revisions]))
+ self.until = min(self.until,
+ max([r.until for r in self._revisions]))
+ self.value = None
+ else:
+ self.value = buildValue(data, self.name, self.label)
+
+ self.spans = None
+
+ # -------------------------------------------------------------------------
+ @property
+ def objects(self) -> dict[str, Object]:
+ if len(self._revisions):
+ out = {}
+ for r in self._revisions:
+ out.update(r.objects)
+ return out
+
+ return self.value.objects
+
+ # -------------------------------------------------------------------------
+ def updateSpans(self, since: int, until: int) -> None:
+ since = max(since, self.since)
+ until = min(until, self.until)
+
+ if len(self._revisions):
+ spans = [[(since, until)]]
+ for r in self._revisions:
+ r.updateSpans(since, until)
+ spans.append(r.spans)
+ self.spans = combineSpans(*spans)
+ else:
+ self.value.updateSpans(since, until)
+ self.spans = self.value.spans
+
+ # -------------------------------------------------------------------------
+ def updateRefs(self, objects: dict[str, 'Object']) -> None:
+ if len(self._revisions):
+ for r in self._revisions:
+ r.updateRefs(objects)
+ else:
+ self.value.updateRefs(objects)
+
+ # -------------------------------------------------------------------------
+ def ref(self, version: int) -> dict[str, str] | None:
+ s = findSpan(self.spans, version)
+ if s is not None:
+ return {
+ '$ref': f'#/definitions/{self.label}@{spanRef(*s)}',
+ }
+ return None
+
+ # -------------------------------------------------------------------------
+ def doc(self, since: int, until: int) -> str | None:
+ if self.content is None:
+ return None
+
+ out = f'.. _`CMakePresets.{self.label}`:\n\n``{self.name}``\n'
+ if self.since > since:
+ out += f' .. presets-versionadded:: {self.since}\n\n'
+ if self.until < until:
+ out += f' .. presets-versionremoved:: {self.until}\n\n'
+ out += indent(self.content)
+
+ return out
+
+ # -------------------------------------------------------------------------
+ def defs(self) -> dict[str, Any]:
+ if len(self._revisions):
+ out = {}
+ for r in self._revisions:
+ out.update(r.defs())
+ return out
+
+ return self.value.defs()
+
+ # -------------------------------------------------------------------------
+ def schema(self, version: int) -> dict[str, Any]:
+ for r in self._revisions:
+ if version >= r.since and version < r.until:
+ return r.value.schema(version)
+ return self.value.schema(version)
+
+
+# =============================================================================
+class CommentProperty(Property):
+ name: str = '$comment'
+ since: int = 10
+
+ # -------------------------------------------------------------------------
+ def __init__(self):
+ data = {
+ 'since': type(self).since,
+ 'id': 'comment',
+ 'type': 'variant',
+ 'items': [
+ {
+ 'type': 'string',
+ 'description': 'A single-line comment.',
+ },
+ {
+ 'type': 'array',
+ 'description': 'A multi-line comment.',
+ 'minItems': 1,
+ 'items': {
+ 'type': 'string',
+ 'description': 'One line of the multi-line comment.',
+ }
+ }
+ ],
+ }
+ super().__init__(data, type(self).name, type(self).name)
+
+ # -------------------------------------------------------------------------
+ def doc(self, since: int, until: int) -> None:
+ return None
+
+
+# -----------------------------------------------------------------------------
+def buildValue(
+ data: Any, name: str, label: str | None = None
+) -> Variant | Object | Array | Ref | Value:
+ if type(data) is dict:
+ if 'anyOf' in data:
+ return Union(data.pop('anyOf'), name, label)
+ elif data['type'] == 'variant':
+ return Variant(data, name, label)
+ elif data['type'] == 'array':
+ return Array(data, name, label)
+ elif data['type'] == 'object':
+ return Object(data, name, label)
+ elif data['type'] == 'ref':
+ return Ref(data)
+
+ return Value(data)
+
+
+# -----------------------------------------------------------------------------
+def extractDivisions(spans: list[tuple[int, int]]) -> set[int]:
+ return {n for s in spans for n in s}
+
+
+# -----------------------------------------------------------------------------
+def trimSpans(spans: list[tuple[int, int]],
+ since: int, until: int) -> list[tuple[int, int]]:
+ divisions = extractDivisions(spans)
+
+ last = since
+ out = []
+
+ for d in sorted(divisions):
+ if d > since:
+ out.append((last, min(d, until)))
+ last = min(d, until)
+ if d >= until:
+ break
+
+ return out
+
+
+# -----------------------------------------------------------------------------
+def combineSpans(*spans: list[tuple[int, int]]) -> list[tuple[int, int]]:
+ divisions = set()
+ for s in spans:
+ divisions.update(extractDivisions(s))
+
+ divisions = sorted(divisions)
+ last = divisions.pop(0)
+ out = []
+
+ for d in divisions:
+ out.append((last, d))
+ last = d
+
+ return out
+
+
+# -----------------------------------------------------------------------------
+def findSpan(spans: list[tuple[int, int]],
+ version: int) -> tuple[int, int] | None:
+ for s in spans:
+ if version >= s[0] and version < s[1]:
+ return s
+
+ return None
+
+
+# -----------------------------------------------------------------------------
+def spanRef(since: int, until: int) -> str:
+ if since + 1 < until:
+ if until > LATEST:
+ return f'v{since}..'
+ else:
+ return f'v{since}..v{until - 1}'
+ return f'v{since}'
+
+
+# -----------------------------------------------------------------------------
+def indent(text: str):
+ return '\n'.join([(' ' + line).rstrip() for line in text.split('\n')])
+
+
+# -----------------------------------------------------------------------------
+def trimDescriptions(data: Any):
+ if type(data) is dict:
+ for k, v in data.items():
+ if type(v) is str and k in {'description', 'sphinxDescription'}:
+ data[k] = v.strip()
+ elif type(v) is dict:
+ data[k] = trimDescriptions(v)
+ elif type(v) is list:
+ data[k] = [trimDescriptions(item) for item in v]
+
+ return data
+
+
+# -----------------------------------------------------------------------------
+def main():
+ # Read the schema definition.
+ with open(PRESETS / SCHEMA_YAML_FILENAME, 'r') as f:
+ schema = yaml.safe_load(f)
+
+ # Extract the current (latest) version.
+ global LATEST
+
+ del schema['definitions']
+ LATEST = schema.pop('version')
+
+ # Remove whitespace around descriptions.
+ schema = trimDescriptions(schema)
+
+ # Extract global type definitions.
+ global TYPES, REFS
+
+ for t in schema.pop('types', []):
+ name = t['id']
+ value = buildValue(t, name)
+ value.updateSpans(1, LATEST + 1)
+ TYPES[name] = value
+
+ for t in TYPES.values():
+ t.updateRefs(TYPES)
+
+ # Reset the spans for references, as these currently contain only spans for
+ # circular references of global types, which are likely broader than the
+ # actual usage spans of those types. We'll recalculate the correct spans
+ # when we update refs from the root object.
+ REFS = {}
+
+ # Parse the root object. This will also recursively parse other objects.
+ root = Object(schema, 'root')
+ root.updateSpans(1, LATEST + 1)
+
+ # Resolve references.
+ objects = root.objects
+
+ types = objects
+ types.update(TYPES)
+
+ root.updateRefs(types)
+
+ for name, value in TYPES.items():
+ span = REFS.get(name)
+ if span is not None:
+ value.updateSpans(*span)
+
+ root.updateSpans(1, LATEST + 1)
+
+ # Extract Sphinx documentation for each object's properties.
+ for n, o in objects.items():
+ doc = o.doc(1, LATEST + 1)
+ if doc is not None:
+ print(f'- Generating reST documentation for {n} properties')
+ with open(PRESETS / f'{o.name}-properties.rst', 'w') as f:
+ print(RST_BANNER, file=f)
+ print(doc, file=f)
+
+ # Generate schema for each version.
+ versions = []
+ for v in range(1, LATEST + 1):
+ vs = root.schema(v, inline={'version'})
+ vs['properties']['version']['const'] = v
+ versions.append(vs)
+
+ # Add definitions and write the schema.
+ types = root.defs(exclude={'version'})
+ for t in TYPES.values():
+ types.update(t.defs())
+
+ schema = {
+ '$schema': 'http://json-schema.org/draft/2020-12/schema#',
+ 'type': 'object',
+ 'oneOf': versions,
+ 'required': ['version'],
+ 'definitions': types
+ }
+
+ with open(PRESETS / SCHEMA_JSON_FILENAME, 'w') as f:
+ print(json.dumps(schema, indent=2), file=f)
+
+
+# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+main()
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 6227b16..3964f5a 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@
readonly ownership="Curl Upstream <curl-library@lists.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-8_18_0"
+readonly tag="curl-8_19_0"
readonly shortlog=false
readonly exact_tree_match=false
readonly paths="
diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash
index 73ee07e..564f346 100755
--- a/Utilities/Scripts/update-libarchive.bash
+++ b/Utilities/Scripts/update-libarchive.bash
@@ -8,7 +8,7 @@
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
readonly subtree="Utilities/cmlibarchive"
readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.8.5"
+readonly tag="v3.8.6"
readonly shortlog=false
readonly exact_tree_match=false
readonly paths="
diff --git a/Utilities/Scripts/update-libuv.bash b/Utilities/Scripts/update-libuv.bash
index b9f664e..19153d0 100755
--- a/Utilities/Scripts/update-libuv.bash
+++ b/Utilities/Scripts/update-libuv.bash
@@ -8,11 +8,7 @@
readonly ownership="libuv upstream <libuv@googlegroups.com>"
readonly subtree="Utilities/cmlibuv"
readonly repo="https://github.com/libuv/libuv.git"
-# We cannot import libuv 1.45 or higher because it has higher
-# minimum system requirements than we do:
-# - It requires C11 atomics from GCC 4.9+. We support GCC 4.8.
-# - It requires Windows 8, we support Windows 7.
-readonly tag="v1.44.2"
+readonly tag="v1.52.0"
readonly shortlog=false
readonly exact_tree_match=false
readonly paths="
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index cb42c87..ae1c518 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeHelp_STANDALONE 1)
- cmake_minimum_required(VERSION 3.13...4.1 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.13...4.2 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index dd8c2f38..c4f7c9e 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -21,6 +21,9 @@
from sphinx import addnodes
from sphinx.directives import ObjectDescription, nl_escape_re
from sphinx.domains import Domain, ObjType
+ from sphinx.domains.changeset import VersionChange
+ from sphinx.domains.changeset import versionlabels, versionlabel_classes
+ from sphinx.domains.std import OptionXRefRole
from sphinx.roles import XRefRole
from sphinx.util import logging, ws_re
from sphinx.util.docutils import ReferenceRole
@@ -33,6 +36,21 @@
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+# BEGIN sphinx tweaks
+
+# Adjust the 'std' domain regex used to parse options so that it recognizes
+# e.g. `-W<name>` as the option `-W` with a value `<name>`, rather than
+# treating the entire string as the option name.
+#
+# See also https://github.com/sphinx-doc/sphinx/issues/14323.
+
+sphinx.domains.std.option_desc_re = (
+ re.compile(r'((?:/|--|-|\+)?[^\s=<]+)(=?\s*.*)'))
+
+# END sphinx tweaks
+
+# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
# BEGIN pygments tweaks
# Override much of pygments' CMakeLexer.
@@ -225,6 +243,7 @@
'policy': _cmake_index_entry('policy'),
'prop_cache': _cmake_index_entry('cache property'),
'prop_dir': _cmake_index_entry('directory property'),
+ 'prop_fs': _cmake_index_entry('file set property'),
'prop_gbl': _cmake_index_entry('global property'),
'prop_inst': _cmake_index_entry('installed file property'),
'prop_sf': _cmake_index_entry('source file property'),
@@ -460,6 +479,8 @@
sigargs = self.targetnames[sig]
else:
def extract_keywords(params):
+ if params[-1].endswith(')'):
+ params[-1] = params[-1][:-1]
for p in params:
if p[0].isalpha():
yield p
@@ -568,6 +589,8 @@
m = CMakeXRefRole._re_guide.match(text)
if m:
text = f'{m.group(2)} <{text}>'
+ elif typ == 'cmake:preset':
+ text = f'CMakePresets.{text}'
return super().__call__(typ, rawtext, text, *args, **kwargs)
# We cannot insert index nodes using the result_nodes method
@@ -582,6 +605,16 @@
# pass
+class CMakeOptionXRefRole(OptionXRefRole):
+ def __init__(self, command: str) -> None:
+ self.command = command
+ super().__init__()
+
+ def __call__(self, typ, rawtext, text, *args, **kwargs):
+ content = f'{text} <{self.command} {re.split(r'[ =]', text)[0]}>'
+ return super().__call__('std:option', text, content, *args, **kwargs)
+
+
class CMakeXRefTransform(Transform):
# Run this transform early since we insert nodes we want
@@ -650,6 +683,7 @@
'policy': ObjType('policy', 'policy'),
'prop_cache': ObjType('prop_cache', 'prop_cache'),
'prop_dir': ObjType('prop_dir', 'prop_dir'),
+ 'prop_fs': ObjType('prop_fs', 'prop_fs'),
'prop_gbl': ObjType('prop_gbl', 'prop_gbl'),
'prop_inst': ObjType('prop_inst', 'prop_inst'),
'prop_sf': ObjType('prop_sf', 'prop_sf'),
@@ -666,6 +700,7 @@
# Other `object_types` cannot be created except by the `CMakeTransform`
}
roles = {
+ # General CMake reference roles.
'cref': CMakeCRefRole(),
'command': CMakeXRefRole(fix_parens=True, lowercase=True),
'cpack_gen': CMakeXRefRole(),
@@ -678,12 +713,21 @@
'policy': CMakeXRefRole(),
'prop_cache': CMakeXRefRole(),
'prop_dir': CMakeXRefRole(),
+ 'prop_fs': CMakeXRefRole(),
'prop_gbl': CMakeXRefRole(),
'prop_inst': CMakeXRefRole(),
'prop_sf': CMakeXRefRole(),
'prop_test': CMakeXRefRole(),
'prop_tgt': CMakeXRefRole(),
'manual': CMakeXRefRole(),
+ 'preset': CMakeXRefRole(lowercase=True, warn_dangling=True),
+ # Roles for program-specific command-line options without the program
+ # name (which add the name to form the ref).
+ 'cmake-option': CMakeOptionXRefRole('cmake'),
+ 'cmake-build-option': CMakeOptionXRefRole('cmake--build'),
+ 'cmake-install-option': CMakeOptionXRefRole('cmake--install'),
+ 'cpack-option': CMakeOptionXRefRole('cpack'),
+ 'ctest-option': CMakeOptionXRefRole('ctest'),
}
initial_data = {
'objects': {}, # fullname -> ObjectEntry
@@ -716,13 +760,29 @@
targetid = f'{typ}:{target}'
obj = self.data['objects'].get(targetid)
- if obj is None and typ == 'command':
- # If 'command(args)' wasn't found, try just 'command'.
- # TODO: remove this fallback? warn?
- # logger.warning(f'no match for {targetid}')
- command = target.split('(')[0]
- targetid = f'{typ}:{command}'
- obj = self.data['objects'].get(targetid)
+ if obj is None:
+ if typ == 'command':
+ # If 'command(args)' wasn't found, try just 'command'.
+ # TODO: remove this fallback? warn?
+ # logger.warning(f'no match for {targetid}')
+ command = target.split('(')[0]
+ targetid = f'{typ}:{command}'
+ obj = self.data['objects'].get(targetid)
+ elif typ == 'preset':
+ # Preset references are really just references to plain old
+ # explicit targets.
+ labels = env.get_domain('std').labels
+ docname, labelid, sectname = labels.get(target, ('', '', ''))
+
+ if not docname:
+ return None
+
+ return make_refnode(builder, fromdocname, docname, labelid,
+ nodes.literal('', sectname), target)
+
+ import sys
+ print(typ, target, node, file=sys.stderr)
+ print(docname, labelid, sectname, file=sys.stderr)
if obj is None:
# TODO: warn somehow?
@@ -752,4 +812,21 @@
app.add_transform(CMakeTransform)
app.add_transform(CMakeXRefTransform)
app.add_domain(CMakeDomain)
+
+ versionlabels.update({
+ 'presets-versionadded': 'Added in presets version %s',
+ 'presets-versionchanged': 'Changed in presets version %s',
+ 'presets-versionremoved': 'Removed in presets version %s',
+ })
+
+ versionlabel_classes.update({
+ 'presets-versionadded': 'added',
+ 'presets-versionchanged': 'changed',
+ 'presets-versionremoved': 'removed',
+ })
+
+ app.add_directive('presets-versionadded', VersionChange)
+ app.add_directive('presets-versionchanged', VersionChange)
+ app.add_directive('presets-versionremoved', VersionChange)
+
return {"parallel_read_safe": True}
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 54ebc8e..7cceaf2 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -26,7 +26,8 @@
'dev',
# NOTE Ignore shared RST files used in `.. include::` directives
'include/*.rst',
- '**/include/*.rst'
+ '**/include/*.rst',
+ 'manual/presets/*.rst',
]
extensions = ['cmake']
diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py
index 61dd819..4283992 100755
--- a/Utilities/Sphinx/create_identifiers.py
+++ b/Utilities/Sphinx/create_identifiers.py
@@ -28,6 +28,7 @@
("genex", "genex"),
("guide", "guide"),
("target property", "prop_tgt"),
+ ("file set property", "prop_fs"),
("test property", "prop_test"),
("source file property", "prop_sf"),
("global property", "prop_gbl"),
diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
index 2576a1a..51a2d94 100644
--- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
+++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
@@ -24,7 +24,7 @@
option(CURL_HIDDEN_SYMBOLS "Hide libcurl internal symbols (=hide all symbols that are not officially external)" ON)
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
-if(WIN32 AND (ENABLE_DEBUG OR ENABLE_CURLDEBUG))
+if(WIN32 AND ENABLE_DEBUG)
# We need to export internal debug functions,
# e.g. curl_easy_perform_ev() or curl_dbg_*(),
# so disable symbol hiding for debug builds and for memory tracking.
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index a06c770..2cf306b 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -27,7 +27,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
-/* */
+
#if defined(sun) || defined(__sun__) || \
defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# if defined(__SVR4) || defined(__srv4__)
@@ -39,7 +39,7 @@
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX41)
# define PLATFORM_AIX_V3
#endif
-/* */
+
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3)
#error "O_NONBLOCK does not work on this platform"
#endif
@@ -128,7 +128,7 @@
#ifdef HAVE_FILE_OFFSET_BITS
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
- We cannot simply define LARGE_OFF_T to be 9223372036854775807,
+ We cannot define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t)1 << 62) - 1 + ((off_t)1 << 62))
diff --git a/Utilities/cmcurl/CMake/FindBrotli.cmake b/Utilities/cmcurl/CMake/FindBrotli.cmake
index 981b30c..b5437e7 100644
--- a/Utilities/cmcurl/CMake/FindBrotli.cmake
+++ b/Utilities/cmcurl/CMake/FindBrotli.cmake
@@ -25,15 +25,16 @@
#
# Input variables:
#
-# - `BROTLI_INCLUDE_DIR`: Absolute path to brotli include directory.
-# - `BROTLICOMMON_LIBRARY`: Absolute path to `brotlicommon` library.
-# - `BROTLIDEC_LIBRARY`: Absolute path to `brotlidec` library.
+# - `BROTLI_INCLUDE_DIR`: Absolute path to brotli include directory.
+# - `BROTLICOMMON_LIBRARY`: Absolute path to `brotlicommon` library.
+# - `BROTLIDEC_LIBRARY`: Absolute path to `brotlidec` library.
+# - `BROTLI_USE_STATIC_LIBS`: Configure for static brotli libraries.
#
# Defines:
#
-# - `BROTLI_FOUND`: System has brotli.
-# - `BROTLI_VERSION`: Version of brotli.
-# - `CURL::brotli`: brotli library target.
+# - `BROTLI_FOUND`: System has brotli.
+# - `BROTLI_VERSION`: Version of brotli.
+# - `CURL::brotli`: brotli library target.
set(_brotli_pc_requires "libbrotlidec" "libbrotlicommon") # order is significant: brotlidec then brotlicommon
@@ -49,11 +50,22 @@
set(Brotli_FOUND TRUE)
set(BROTLI_FOUND TRUE)
set(BROTLI_VERSION ${_brotli_libbrotlicommon_VERSION})
+ if(BROTLI_USE_STATIC_LIBS)
+ set(_brotli_CFLAGS "${_brotli_STATIC_CFLAGS}")
+ set(_brotli_INCLUDE_DIRS "${_brotli_STATIC_INCLUDE_DIRS}")
+ set(_brotli_LIBRARY_DIRS "${_brotli_STATIC_LIBRARY_DIRS}")
+ set(_brotli_LIBRARIES "${_brotli_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found Brotli (via pkg-config): ${_brotli_INCLUDE_DIRS} (found version \"${BROTLI_VERSION}\")")
else()
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
- find_library(BROTLICOMMON_LIBRARY NAMES "brotlicommon")
- find_library(BROTLIDEC_LIBRARY NAMES "brotlidec")
+ if(BROTLI_USE_STATIC_LIBS)
+ find_library(BROTLICOMMON_LIBRARY NAMES "brotlicommon-static" "brotlicommon")
+ find_library(BROTLIDEC_LIBRARY NAMES "brotlidec-static" "brotlidec")
+ else()
+ find_library(BROTLICOMMON_LIBRARY NAMES "brotlicommon")
+ find_library(BROTLIDEC_LIBRARY NAMES "brotlidec")
+ endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Brotli
diff --git a/Utilities/cmcurl/CMake/FindCares.cmake b/Utilities/cmcurl/CMake/FindCares.cmake
index 4a20bc0..3c05c3b 100644
--- a/Utilities/cmcurl/CMake/FindCares.cmake
+++ b/Utilities/cmcurl/CMake/FindCares.cmake
@@ -25,14 +25,15 @@
#
# Input variables:
#
-# - `CARES_INCLUDE_DIR`: Absolute path to c-ares include directory.
-# - `CARES_LIBRARY`: Absolute path to `cares` library.
+# - `CARES_INCLUDE_DIR`: Absolute path to c-ares include directory.
+# - `CARES_LIBRARY`: Absolute path to `cares` library.
+# - `CARES_USE_STATIC_LIBS`: Configure for static c-ares libraries.
#
# Defines:
#
-# - `CARES_FOUND`: System has c-ares.
-# - `CARES_VERSION`: Version of c-ares.
-# - `CURL::cares`: c-ares library target.
+# - `CARES_FOUND`: System has c-ares.
+# - `CARES_VERSION`: Version of c-ares.
+# - `CURL::cares`: c-ares library target.
set(_cares_pc_requires "libcares")
@@ -47,10 +48,21 @@
set(Cares_FOUND TRUE)
set(CARES_FOUND TRUE)
set(CARES_VERSION ${_cares_VERSION})
+ if(CARES_USE_STATIC_LIBS)
+ set(_cares_CFLAGS "${_cares_STATIC_CFLAGS}")
+ set(_cares_INCLUDE_DIRS "${_cares_STATIC_INCLUDE_DIRS}")
+ set(_cares_LIBRARY_DIRS "${_cares_STATIC_LIBRARY_DIRS}")
+ set(_cares_LIBRARIES "${_cares_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found Cares (via pkg-config): ${_cares_INCLUDE_DIRS} (found version \"${CARES_VERSION}\")")
else()
find_path(CARES_INCLUDE_DIR NAMES "ares.h")
- find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares")
+ if(CARES_USE_STATIC_LIBS)
+ set(_cares_CFLAGS "-DCARES_STATICLIB")
+ find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares_static" "cares")
+ else()
+ find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares")
+ endif()
unset(CARES_VERSION CACHE)
if(CARES_INCLUDE_DIR AND EXISTS "${CARES_INCLUDE_DIR}/ares_version.h")
diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake
index 106c4c4..e36f75b 100644
--- a/Utilities/cmcurl/CMake/FindGSS.cmake
+++ b/Utilities/cmcurl/CMake/FindGSS.cmake
@@ -25,15 +25,15 @@
#
# Input variables:
#
-# - `GSS_ROOT_DIR`: Absolute path to the root installation of GSS. (also supported as environment)
+# - `GSS_ROOT_DIR`: Absolute path to the root installation of GSS. (also supported as environment)
#
# Defines:
#
-# - `GSS_FOUND`: System has a GSS library.
-# - `GSS_VERSION`: This is set to version advertised by pkg-config or read from manifest.
-# In case the library is found but no version info available it is set to "unknown"
-# - `CURL::gss`: GSS library target.
-# - CURL_GSS_FLAVOUR`: Custom property. "GNU" or "MIT" if detected.
+# - `GSS_FOUND`: System has a GSS library.
+# - `GSS_VERSION`: This is set to version advertised by pkg-config or read from manifest.
+# In case the library is found but no version info available it is set to "unknown"
+# - `CURL::gss`: GSS library target.
+# - `CURL_GSS_FLAVOUR`: Custom property. "GNU" or "MIT" if detected.
set(_gnu_modname "gss")
set(_mit_modname "mit-krb5-gssapi")
diff --git a/Utilities/cmcurl/CMake/FindLibssh.cmake b/Utilities/cmcurl/CMake/FindLibssh.cmake
index ad1248f..732ab8e 100644
--- a/Utilities/cmcurl/CMake/FindLibssh.cmake
+++ b/Utilities/cmcurl/CMake/FindLibssh.cmake
@@ -25,14 +25,15 @@
#
# Input variables:
#
-# - `LIBSSH_INCLUDE_DIR`: Absolute path to libssh include directory.
-# - `LIBSSH_LIBRARY`: Absolute path to `libssh` library.
+# - `LIBSSH_INCLUDE_DIR`: Absolute path to libssh include directory.
+# - `LIBSSH_LIBRARY`: Absolute path to `libssh` library.
+# - `LIBSSH_USE_STATIC_LIBS`: Configure for static libssh libraries.
#
# Defines:
#
-# - `LIBSSH_FOUND`: System has libssh.
-# - `LIBSSH_VERSION`: Version of libssh.
-# - `CURL::libssh`: libssh library target.
+# - `LIBSSH_FOUND`: System has libssh.
+# - `LIBSSH_VERSION`: Version of libssh.
+# - `CURL::libssh`: libssh library target.
set(_libssh_pc_requires "libssh")
@@ -47,10 +48,21 @@
set(Libssh_FOUND TRUE)
set(LIBSSH_FOUND TRUE)
set(LIBSSH_VERSION ${_libssh_VERSION})
+ if(LIBSSH_USE_STATIC_LIBS)
+ set(_libssh_CFLAGS "${_libssh_STATIC_CFLAGS}")
+ set(_libssh_INCLUDE_DIRS "${_libssh_STATIC_INCLUDE_DIRS}")
+ set(_libssh_LIBRARY_DIRS "${_libssh_STATIC_LIBRARY_DIRS}")
+ set(_libssh_LIBRARIES "${_libssh_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found Libssh (via pkg-config): ${_libssh_INCLUDE_DIRS} (found version \"${LIBSSH_VERSION}\")")
else()
find_path(LIBSSH_INCLUDE_DIR NAMES "libssh/libssh.h")
- find_library(LIBSSH_LIBRARY NAMES "ssh" "libssh")
+ if(LIBSSH_USE_STATIC_LIBS)
+ set(_libssh_CFLAGS "-DLIBSSH_STATIC")
+ find_library(LIBSSH_LIBRARY NAMES "ssh_static" "libssh_static" "ssh" "libssh")
+ else()
+ find_library(LIBSSH_LIBRARY NAMES "ssh" "libssh")
+ endif()
unset(LIBSSH_VERSION CACHE)
if(LIBSSH_INCLUDE_DIR AND EXISTS "${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h")
diff --git a/Utilities/cmcurl/CMake/FindLibssh2.cmake b/Utilities/cmcurl/CMake/FindLibssh2.cmake
index 330611b..abed471 100644
--- a/Utilities/cmcurl/CMake/FindLibssh2.cmake
+++ b/Utilities/cmcurl/CMake/FindLibssh2.cmake
@@ -25,14 +25,15 @@
#
# Input variables:
#
-# - `LIBSSH2_INCLUDE_DIR`: Absolute path to libssh2 include directory.
-# - `LIBSSH2_LIBRARY`: Absolute path to `libssh2` library.
+# - `LIBSSH2_INCLUDE_DIR`: Absolute path to libssh2 include directory.
+# - `LIBSSH2_LIBRARY`: Absolute path to `libssh2` library.
+# - `LIBSSH2_USE_STATIC_LIBS`: Configure for static libssh2 libraries.
#
# Defines:
#
-# - `LIBSSH2_FOUND`: System has libssh2.
-# - `LIBSSH2_VERSION`: Version of libssh2.
-# - `CURL::libssh2`: libssh2 library target.
+# - `LIBSSH2_FOUND`: System has libssh2.
+# - `LIBSSH2_VERSION`: Version of libssh2.
+# - `CURL::libssh2`: libssh2 library target.
set(_libssh2_pc_requires "libssh2")
@@ -47,10 +48,20 @@
set(Libssh2_FOUND TRUE)
set(LIBSSH2_FOUND TRUE)
set(LIBSSH2_VERSION ${_libssh2_VERSION})
+ if(LIBSSH2_USE_STATIC_LIBS)
+ set(_libssh2_CFLAGS "${_libssh2_STATIC_CFLAGS}")
+ set(_libssh2_INCLUDE_DIRS "${_libssh2_STATIC_INCLUDE_DIRS}")
+ set(_libssh2_LIBRARY_DIRS "${_libssh2_STATIC_LIBRARY_DIRS}")
+ set(_libssh2_LIBRARIES "${_libssh2_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found Libssh2 (via pkg-config): ${_libssh2_INCLUDE_DIRS} (found version \"${LIBSSH2_VERSION}\")")
else()
find_path(LIBSSH2_INCLUDE_DIR NAMES "libssh2.h")
- find_library(LIBSSH2_LIBRARY NAMES "ssh2" "libssh2")
+ if(LIBSSH2_USE_STATIC_LIBS)
+ find_library(LIBSSH2_LIBRARY NAMES "ssh2_static" "libssh2_static" "ssh2" "libssh2")
+ else()
+ find_library(LIBSSH2_LIBRARY NAMES "ssh2" "libssh2")
+ endif()
unset(LIBSSH2_VERSION CACHE)
if(LIBSSH2_INCLUDE_DIR AND EXISTS "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
diff --git a/Utilities/cmcurl/CMake/FindMbedTLS.cmake b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
index 97201ab..8b67ce9 100644
--- a/Utilities/cmcurl/CMake/FindMbedTLS.cmake
+++ b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
@@ -25,16 +25,17 @@
#
# Input variables:
#
-# - `MBEDTLS_INCLUDE_DIR`: Absolute path to mbedTLS include directory.
-# - `MBEDTLS_LIBRARY`: Absolute path to `mbedtls` library.
-# - `MBEDX509_LIBRARY`: Absolute path to `mbedx509` library.
-# - `MBEDCRYPTO_LIBRARY`: Absolute path to `mbedcrypto` library.
+# - `MBEDTLS_INCLUDE_DIR`: Absolute path to mbedTLS include directory.
+# - `MBEDTLS_LIBRARY`: Absolute path to `mbedtls` library.
+# - `MBEDX509_LIBRARY`: Absolute path to `mbedx509` library.
+# - `MBEDCRYPTO_LIBRARY`: Absolute path to `mbedcrypto` library.
+# - `MBEDTLS_USE_STATIC_LIBS`: Configure for static mbedTLS libraries.
#
# Defines:
#
-# - `MBEDTLS_FOUND`: System has mbedTLS.
-# - `MBEDTLS_VERSION`: Version of mbedTLS.
-# - `CURL::mbedtls`: mbedTLS library target.
+# - `MBEDTLS_FOUND`: System has mbedTLS.
+# - `MBEDTLS_VERSION`: Version of mbedTLS.
+# - `CURL::mbedtls`: mbedTLS library target.
if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR)
message(WARNING "MBEDTLS_INCLUDE_DIRS is deprecated, use MBEDTLS_INCLUDE_DIR instead.")
@@ -57,14 +58,27 @@
set(MbedTLS_FOUND TRUE)
set(MBEDTLS_FOUND TRUE)
set(MBEDTLS_VERSION ${_mbedtls_mbedtls_VERSION})
+ if(MBEDTLS_USE_STATIC_LIBS)
+ set(_mbedtls_CFLAGS "${_mbedtls_STATIC_CFLAGS}")
+ set(_mbedtls_INCLUDE_DIRS "${_mbedtls_STATIC_INCLUDE_DIRS}")
+ set(_mbedtls_LIBRARY_DIRS "${_mbedtls_STATIC_LIBRARY_DIRS}")
+ set(_mbedtls_LIBRARIES "${_mbedtls_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found MbedTLS (via pkg-config): ${_mbedtls_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")")
else()
set(_mbedtls_pc_requires "") # Depend on pkg-config only when found via pkg-config
find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h")
- find_library(MBEDTLS_LIBRARY NAMES "mbedtls" "libmbedtls")
- find_library(MBEDX509_LIBRARY NAMES "mbedx509" "libmbedx509")
- find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto" "libmbedcrypto")
+ if(MBEDTLS_USE_STATIC_LIBS)
+ find_library(MBEDTLS_LIBRARY NAMES "mbedtls_static" "libmbedtls_static" "mbedtls" "libmbedtls")
+ find_library(MBEDX509_LIBRARY NAMES "mbedx509_static" "libmbedx509_static" "mbedx509" "libmbedx509")
+ find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto_static" "libmbedcrypto_static" "mbedcrypto" "libmbedcrypto"
+ "tfpsacrypto_static" "libtfpsacrypto_static" "tfpsacrypto" "libtfpsacrypto")
+ else()
+ find_library(MBEDTLS_LIBRARY NAMES "mbedtls" "libmbedtls")
+ find_library(MBEDX509_LIBRARY NAMES "mbedx509" "libmbedx509")
+ find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto" "libmbedcrypto" "tfpsacrypto" "libtfpsacrypto")
+ endif()
unset(MBEDTLS_VERSION CACHE)
if(MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
index 8304345..b2a8c97 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
@@ -25,14 +25,15 @@
#
# Input variables:
#
-# - `NGHTTP2_INCLUDE_DIR`: Absolute path to nghttp2 include directory.
-# - `NGHTTP2_LIBRARY`: Absolute path to `nghttp2` library.
+# - `NGHTTP2_INCLUDE_DIR`: Absolute path to nghttp2 include directory.
+# - `NGHTTP2_LIBRARY`: Absolute path to `nghttp2` library.
+# - `NGHTTP2_USE_STATIC_LIBS`: Configure for static nghttp2 libraries.
#
# Defines:
#
-# - `NGHTTP2_FOUND`: System has nghttp2.
-# - `NGHTTP2_VERSION`: Version of nghttp2.
-# - `CURL::nghttp2`: nghttp2 library target.
+# - `NGHTTP2_FOUND`: System has nghttp2.
+# - `NGHTTP2_VERSION`: Version of nghttp2.
+# - `CURL::nghttp2`: nghttp2 library target.
set(_nghttp2_pc_requires "libnghttp2")
@@ -46,10 +47,21 @@
if(_nghttp2_FOUND)
set(NGHTTP2_FOUND TRUE)
set(NGHTTP2_VERSION ${_nghttp2_VERSION})
+ if(NGHTTP2_USE_STATIC_LIBS)
+ set(_nghttp2_CFLAGS "${_nghttp2_STATIC_CFLAGS}")
+ set(_nghttp2_INCLUDE_DIRS "${_nghttp2_STATIC_INCLUDE_DIRS}")
+ set(_nghttp2_LIBRARY_DIRS "${_nghttp2_STATIC_LIBRARY_DIRS}")
+ set(_nghttp2_LIBRARIES "${_nghttp2_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found NGHTTP2 (via pkg-config): ${_nghttp2_INCLUDE_DIRS} (found version \"${NGHTTP2_VERSION}\")")
else()
find_path(NGHTTP2_INCLUDE_DIR NAMES "nghttp2/nghttp2.h")
- find_library(NGHTTP2_LIBRARY NAMES "nghttp2" "nghttp2_static")
+ if(NGHTTP2_USE_STATIC_LIBS)
+ set(_nghttp2_CFLAGS "-DNGHTTP2_STATICLIB")
+ find_library(NGHTTP2_LIBRARY NAMES "nghttp2_static" "nghttp2")
+ else()
+ find_library(NGHTTP2_LIBRARY NAMES "nghttp2" "nghttp2_static")
+ endif()
unset(NGHTTP2_VERSION CACHE)
if(NGHTTP2_INCLUDE_DIR AND EXISTS "${NGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2ver.h")
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
index 37ebfe1..57550bf 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
@@ -25,14 +25,15 @@
#
# Input variables:
#
-# - `NGHTTP3_INCLUDE_DIR`: Absolute path to nghttp3 include directory.
-# - `NGHTTP3_LIBRARY`: Absolute path to `nghttp3` library.
+# - `NGHTTP3_INCLUDE_DIR`: Absolute path to nghttp3 include directory.
+# - `NGHTTP3_LIBRARY`: Absolute path to `nghttp3` library.
+# - `NGHTTP3_USE_STATIC_LIBS`: Configure for static nghttp3 libraries.
#
# Defines:
#
-# - `NGHTTP3_FOUND`: System has nghttp3.
-# - `NGHTTP3_VERSION`: Version of nghttp3.
-# - `CURL::nghttp3`: nghttp3 library target.
+# - `NGHTTP3_FOUND`: System has nghttp3.
+# - `NGHTTP3_VERSION`: Version of nghttp3.
+# - `CURL::nghttp3`: nghttp3 library target.
set(_nghttp3_pc_requires "libnghttp3")
@@ -46,10 +47,21 @@
if(_nghttp3_FOUND)
set(NGHTTP3_FOUND TRUE)
set(NGHTTP3_VERSION ${_nghttp3_VERSION})
+ if(NGHTTP3_USE_STATIC_LIBS)
+ set(_nghttp3_CFLAGS "${_nghttp3_STATIC_CFLAGS}")
+ set(_nghttp3_INCLUDE_DIRS "${_nghttp3_STATIC_INCLUDE_DIRS}")
+ set(_nghttp3_LIBRARY_DIRS "${_nghttp3_STATIC_LIBRARY_DIRS}")
+ set(_nghttp3_LIBRARIES "${_nghttp3_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found NGHTTP3 (via pkg-config): ${_nghttp3_INCLUDE_DIRS} (found version \"${NGHTTP3_VERSION}\")")
else()
find_path(NGHTTP3_INCLUDE_DIR NAMES "nghttp3/nghttp3.h")
- find_library(NGHTTP3_LIBRARY NAMES "nghttp3")
+ if(NGHTTP3_USE_STATIC_LIBS)
+ set(_nghttp3_CFLAGS "-DNGHTTP3_STATICLIB")
+ find_library(NGHTTP3_LIBRARY NAMES "nghttp3_static" "nghttp3")
+ else()
+ find_library(NGHTTP3_LIBRARY NAMES "nghttp3")
+ endif()
unset(NGHTTP3_VERSION CACHE)
if(NGHTTP3_INCLUDE_DIR AND EXISTS "${NGHTTP3_INCLUDE_DIR}/nghttp3/version.h")
diff --git a/Utilities/cmcurl/CMake/FindNGTCP2.cmake b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
index 416ea45..615ee4a 100644
--- a/Utilities/cmcurl/CMake/FindNGTCP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
@@ -43,6 +43,7 @@
# - `NGTCP2_CRYPTO_OSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_ossl` library.
# - `NGTCP2_CRYPTO_QUICTLS_LIBRARY`: Absolute path to `ngtcp2_crypto_quictls` library.
# - `NGTCP2_CRYPTO_WOLFSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_wolfssl` library.
+# - `NGTCP2_USE_STATIC_LIBS`: Configure for static ngtcp2 libraries.
#
# Defines:
#
@@ -84,10 +85,21 @@
if(_ngtcp2_FOUND)
set(NGTCP2_FOUND TRUE)
set(NGTCP2_VERSION ${_ngtcp2_libngtcp2_VERSION})
+ if(NGTCP2_USE_STATIC_LIBS)
+ set(_ngtcp2_CFLAGS "${_ngtcp2_STATIC_CFLAGS}")
+ set(_ngtcp2_INCLUDE_DIRS "${_ngtcp2_STATIC_INCLUDE_DIRS}")
+ set(_ngtcp2_LIBRARY_DIRS "${_ngtcp2_STATIC_LIBRARY_DIRS}")
+ set(_ngtcp2_LIBRARIES "${_ngtcp2_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found NGTCP2 (via pkg-config): ${_ngtcp2_INCLUDE_DIRS} (found version \"${NGTCP2_VERSION}\")")
else()
find_path(NGTCP2_INCLUDE_DIR NAMES "ngtcp2/ngtcp2.h")
- find_library(NGTCP2_LIBRARY NAMES "ngtcp2")
+ if(NGTCP2_USE_STATIC_LIBS)
+ set(_ngtcp2_CFLAGS "-DNGTCP2_STATICLIB")
+ find_library(NGTCP2_LIBRARY NAMES "ngtcp2_static" "ngtcp2")
+ else()
+ find_library(NGTCP2_LIBRARY NAMES "ngtcp2")
+ endif()
unset(NGTCP2_VERSION CACHE)
if(NGTCP2_INCLUDE_DIR AND EXISTS "${NGTCP2_INCLUDE_DIR}/ngtcp2/version.h")
@@ -105,7 +117,13 @@
else()
get_filename_component(_ngtcp2_library_dir "${NGTCP2_LIBRARY}" DIRECTORY)
endif()
- find_library(${_crypto_library_upper}_LIBRARY NAMES ${_crypto_library_lower} HINTS ${_ngtcp2_library_dir})
+ if(NGTCP2_USE_STATIC_LIBS)
+ find_library(${_crypto_library_upper}_LIBRARY NAMES ${_crypto_library_lower}_static ${_crypto_library_lower}
+ HINTS ${_ngtcp2_library_dir})
+ else()
+ find_library(${_crypto_library_upper}_LIBRARY NAMES ${_crypto_library_lower}
+ HINTS ${_ngtcp2_library_dir})
+ endif()
if(${_crypto_library_upper}_LIBRARY)
set(NGTCP2_${_ngtcp2_crypto_backend}_FOUND TRUE)
diff --git a/Utilities/cmcurl/CMake/FindZstd.cmake b/Utilities/cmcurl/CMake/FindZstd.cmake
index 954a827..baf6148 100644
--- a/Utilities/cmcurl/CMake/FindZstd.cmake
+++ b/Utilities/cmcurl/CMake/FindZstd.cmake
@@ -25,14 +25,15 @@
#
# Input variables:
#
-# - `ZSTD_INCLUDE_DIR`: Absolute path to zstd include directory.
-# - `ZSTD_LIBRARY`: Absolute path to `zstd` library.
+# - `ZSTD_INCLUDE_DIR`: Absolute path to zstd include directory.
+# - `ZSTD_LIBRARY`: Absolute path to `zstd` library.
+# - `ZSTD_USE_STATIC_LIBS`: Configure for static zstd libraries.
#
# Defines:
#
-# - `ZSTD_FOUND`: System has zstd.
-# - `ZSTD_VERSION`: Version of zstd.
-# - `CURL::zstd`: zstd library target.
+# - `ZSTD_FOUND`: System has zstd.
+# - `ZSTD_VERSION`: Version of zstd.
+# - `CURL::zstd`: zstd library target.
if(DEFINED Zstd_INCLUDE_DIR AND NOT DEFINED ZSTD_INCLUDE_DIR)
message(WARNING "Zstd_INCLUDE_DIR is deprecated, use ZSTD_INCLUDE_DIR instead.")
@@ -56,10 +57,20 @@
set(Zstd_FOUND TRUE)
set(ZSTD_FOUND TRUE)
set(ZSTD_VERSION ${_zstd_VERSION})
+ if(ZSTD_USE_STATIC_LIBS)
+ set(_zstd_CFLAGS "${_zstd_STATIC_CFLAGS}")
+ set(_zstd_INCLUDE_DIRS "${_zstd_STATIC_INCLUDE_DIRS}")
+ set(_zstd_LIBRARY_DIRS "${_zstd_STATIC_LIBRARY_DIRS}")
+ set(_zstd_LIBRARIES "${_zstd_STATIC_LIBRARIES}")
+ endif()
message(STATUS "Found Zstd (via pkg-config): ${_zstd_INCLUDE_DIRS} (found version \"${ZSTD_VERSION}\")")
else()
find_path(ZSTD_INCLUDE_DIR NAMES "zstd.h")
- find_library(ZSTD_LIBRARY NAMES "zstd")
+ if(ZSTD_USE_STATIC_LIBS)
+ find_library(ZSTD_LIBRARY NAMES "zstd_static" "zstd")
+ else()
+ find_library(ZSTD_LIBRARY NAMES "zstd")
+ endif()
unset(ZSTD_VERSION CACHE)
if(ZSTD_INCLUDE_DIR AND EXISTS "${ZSTD_INCLUDE_DIR}/zstd.h")
diff --git a/Utilities/cmcurl/CMake/Macros.cmake b/Utilities/cmcurl/CMake/Macros.cmake
index ca63301..e182f21 100644
--- a/Utilities/cmcurl/CMake/Macros.cmake
+++ b/Utilities/cmcurl/CMake/Macros.cmake
@@ -71,9 +71,17 @@
set_property(CACHE ${_option_name} PROPERTY STRINGS "AUTO" "ON" "OFF")
if(${_option_name} STREQUAL "AUTO")
- find_package(${_find_name})
+ if(_find_name STREQUAL "ZLIB")
+ find_package(${_find_name})
+ else()
+ find_package(${_find_name} MODULE)
+ endif()
elseif(${_option_name})
- find_package(${_find_name} REQUIRED)
+ if(_find_name STREQUAL "ZLIB")
+ find_package(${_find_name} REQUIRED)
+ else()
+ find_package(${_find_name} MODULE REQUIRED)
+ endif()
else()
string(TOUPPER "${_find_name}" _find_name_upper)
set(${_find_name}_FOUND OFF) # cmake-lint: disable=C0103
@@ -102,24 +110,24 @@
# Internal: Recurse into target libraries and collect their include directories
# and macro definitions.
-macro(curl_collect_target_options _target)
- get_target_property(_val ${_target} INTERFACE_INCLUDE_DIRECTORIES)
- if(_val)
- list(APPEND _includes ${_val})
- endif()
- get_target_property(_val ${_target} INCLUDE_DIRECTORIES)
- if(_val)
- list(APPEND _includes ${_val})
- endif()
- get_target_property(_val ${_target} COMPILE_DEFINITIONS)
+macro(curl_collect_target_compile_options _target)
+ get_target_property(_val ${_target} INTERFACE_COMPILE_DEFINITIONS)
if(_val)
list(APPEND _definitions ${_val})
endif()
+ get_target_property(_val ${_target} INTERFACE_INCLUDE_DIRECTORIES)
+ if(_val)
+ list(APPEND _incsys ${_val})
+ endif()
+ get_target_property(_val ${_target} INTERFACE_COMPILE_OPTIONS)
+ if(_val)
+ list(APPEND _options ${_val})
+ endif()
get_target_property(_val ${_target} LINK_LIBRARIES)
if(_val)
foreach(_lib IN LISTS _val)
if(TARGET "${_lib}")
- curl_collect_target_options(${_lib})
+ curl_collect_target_compile_options(${_lib})
endif()
endforeach()
endif()
@@ -127,35 +135,94 @@
endmacro()
# Create a clang-tidy target for test targets
-macro(curl_add_clang_tidy_test_target _target_clang_tidy _target)
+function(curl_add_clang_tidy_test_target _target_clang_tidy _target)
if(CURL_CLANG_TIDY)
- set(_includes "")
set(_definitions "")
+ set(_includes "")
+ set(_incsys "")
+ set(_options "")
- # Collect header directories and macro definitions applying to the directory
- get_directory_property(_val INCLUDE_DIRECTORIES)
- if(_val)
- list(APPEND _includes ${_val})
- endif()
+ # Make a list of known system include directories
+ set(_sys_incdirs "${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}")
+ foreach(_inc IN LISTS CMAKE_SYSTEM_PREFIX_PATH)
+ if(NOT _inc MATCHES "/$")
+ string(APPEND _inc "/")
+ endif()
+ string(APPEND _inc "include")
+ if(NOT _inc IN_LIST _sys_incdirs AND IS_DIRECTORY "${_inc}")
+ list(APPEND _sys_incdirs "${_inc}")
+ endif()
+ endforeach()
+
+ # Collect options applying to the directory
get_directory_property(_val COMPILE_DEFINITIONS)
if(_val)
list(APPEND _definitions ${_val})
endif()
- unset(_val)
+ get_directory_property(_val INCLUDE_DIRECTORIES)
+ if(_val)
+ list(APPEND _includes ${_val})
+ endif()
+ get_directory_property(_val COMPILE_OPTIONS)
+ if(_val)
+ list(APPEND _options ${_val})
+ endif()
+
+ # Collect options applying to the target
+ get_target_property(_val ${_target} COMPILE_DEFINITIONS)
+ if(_val)
+ list(APPEND _definitions ${_val})
+ endif()
+ get_target_property(_val ${_target} INCLUDE_DIRECTORIES)
+ if(_val)
+ list(APPEND _includes ${_val})
+ endif()
+ get_target_property(_val ${_target} COMPILE_OPTIONS)
+ if(_val)
+ list(APPEND _options ${_val})
+ endif()
# Collect header directories and macro definitions from lib dependencies
- curl_collect_target_options(${_target})
-
- list(REMOVE_ITEM _includes "")
- string(REPLACE ";" ";-I" _includes ";${_includes}")
- list(REMOVE_DUPLICATES _includes)
+ curl_collect_target_compile_options(${_target})
list(REMOVE_ITEM _definitions "")
string(REPLACE ";" ";-D" _definitions ";${_definitions}")
list(REMOVE_DUPLICATES _definitions)
list(SORT _definitions) # Sort like CMake does
+ list(REMOVE_ITEM _includes "")
+ string(REPLACE ";" ";-I" _includes ";${_includes}")
+ list(REMOVE_DUPLICATES _includes)
+
+ set(_incsys_tmp ${_incsys})
+ list(REMOVE_DUPLICATES _incsys_tmp)
+ set(_incsys "")
+ set(_incsystop "")
+ foreach(_inc IN LISTS _incsys_tmp)
+ if(_inc IN_LIST _sys_incdirs)
+ list(APPEND _incsystop "${_inc}") # Save system prefixes to re-add them later to the end of list
+ continue()
+ endif()
+ # Avoid empty and '$<INSTALL_INTERFACE:include>' items. The latter
+ # evaluates to an empty path in this context. Also skip
+ # '$<BUILD_INTERFACE:curl-include>', as already present in '_includes'.
+ if(_inc AND
+ NOT _inc MATCHES "INSTALL_INTERFACE:" AND
+ NOT _inc MATCHES "BUILD_INTERFACE:")
+ list(APPEND _incsys "-isystem" "${_inc}")
+ endif()
+ endforeach()
+ foreach(_inc IN LISTS _incsystop)
+ list(APPEND _incsys "-isystem" "${_inc}")
+ endforeach()
+
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ list(REMOVE_DUPLICATES _options) # Keep the first of duplicates to imitate CMake
+ else()
+ set(_options)
+ endif()
+
# Assemble source list
set(_sources "")
foreach(_source IN ITEMS ${ARGN})
@@ -165,14 +232,23 @@
list(APPEND _sources "${_source}")
endforeach()
+ set(_cc "${CMAKE_C_COMPILER}")
+ if(CMAKE_C_COMPILER_TARGET AND CMAKE_C_COMPILE_OPTIONS_TARGET)
+ list(APPEND _cc "${CMAKE_C_COMPILE_OPTIONS_TARGET}${CMAKE_C_COMPILER_TARGET}")
+ endif()
+ if(APPLE AND CMAKE_OSX_SYSROOT)
+ list(APPEND _cc "-isysroot" "${CMAKE_OSX_SYSROOT}")
+ elseif(CMAKE_SYSROOT AND CMAKE_C_COMPILE_OPTIONS_SYSROOT)
+ list(APPEND _cc "${CMAKE_C_COMPILE_OPTIONS_SYSROOT}${CMAKE_SYSROOT}")
+ endif()
+
+ # Pass -clang-diagnostic-unused-function to disable -Wunused-function implied by -Wunused
add_custom_target(${_target_clang_tidy} USES_TERMINAL
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
- COMMAND ${CMAKE_C_CLANG_TIDY} ${_sources} -- ${_includes} ${_definitions}
+ COMMAND ${CMAKE_C_CLANG_TIDY}
+ "--checks=-clang-diagnostic-unused-function"
+ ${_sources} -- ${_cc} ${_definitions} ${_includes} ${_incsys} ${_options}
DEPENDS ${_sources})
add_dependencies(tests-clang-tidy ${_target_clang_tidy})
-
- unset(_includes)
- unset(_definitions)
- unset(_sources)
endif()
-endmacro()
+endfunction()
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index 9f59e0d..650a42d 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -50,19 +50,6 @@
cmake_pop_check_state()
endif()
-if(NOT WIN32)
- set(_source_epilogue "#undef inline")
- curl_add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
- check_c_source_compiles("${_source_epilogue}
- #include <sys/socket.h>
- int main(void)
- {
- int flag = MSG_NOSIGNAL;
- (void)flag;
- return 0;
- }" HAVE_MSG_NOSIGNAL)
-endif()
-
set(_source_epilogue "#undef inline")
check_c_source_compiles("${_source_epilogue}
#ifdef _MSC_VER
diff --git a/Utilities/cmcurl/CMake/PickyWarnings.cmake b/Utilities/cmcurl/CMake/PickyWarnings.cmake
index 5e643c5..1b67b0b 100644
--- a/Utilities/cmcurl/CMake/PickyWarnings.cmake
+++ b/Utilities/cmcurl/CMake/PickyWarnings.cmake
@@ -117,7 +117,7 @@
-Waddress # clang 2.7 gcc 4.3
-Wattributes # clang 2.7 gcc 4.1
-Wcast-align # clang 1.0 gcc 4.2
- -Wcast-qual # clang 3.0 gcc 3.4.6
+ -Wcast-qual # clang 2.7 gcc 3.4.6
-Wdeclaration-after-statement # clang 1.0 gcc 3.4
-Wdiv-by-zero # clang 2.7 gcc 4.1
-Wempty-body # clang 2.7 gcc 4.3
@@ -127,7 +127,6 @@
-Wignored-qualifiers # clang 2.8 gcc 4.3
-Wmissing-field-initializers # clang 2.7 gcc 4.1
-Wmissing-noreturn # clang 2.7 gcc 4.1
- -Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0)
-Wno-padded # clang 2.9 gcc 4.1 # Not used: We cannot change public structs
-Wno-sign-conversion # clang 2.9 gcc 4.3
-Wno-switch-default # clang 2.7 gcc 4.1 # Not used: Annoying to fix or silence
@@ -148,10 +147,10 @@
list(APPEND _picky_enable
${_picky_common_old}
-Wconditional-uninitialized # clang 3.0
- -Wno-used-but-marked-unused # clang 3.0 # Triggered by typecheck-gcc.h (with clang 14+)
+ -Wno-used-but-marked-unused # clang 2.9 # Triggered by typecheck-gcc.h with clang 14+, dependency headers
-Wshift-sign-overflow # clang 2.9
-Wshorten-64-to-32 # clang 1.0
- -Wformat=2 # clang 3.0 gcc 4.8
+ -Wformat=2 # clang 2.7 gcc 4.8
)
if(NOT MSVC)
list(APPEND _picky_enable
@@ -162,7 +161,7 @@
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.1)
list(APPEND _picky_enable
-Wno-covered-switch-default # clang 3.1 appleclang 3.1 # Annoying to fix or silence
- -Wno-disabled-macro-expansion # clang 3.1 appleclang 3.1 # Triggered by typecheck-gcc.h (with clang 14+)
+ -Wno-disabled-macro-expansion # clang 3.1 appleclang 3.1 # Triggered by curl/curl.h, standard headers
)
if(MSVC)
list(APPEND _picky_enable
@@ -226,6 +225,14 @@
-Wno-reserved-macro-identifier # clang 13.0 appleclang 13.1 # External macros have to be set sometimes
)
endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0.3))
+ if(CMAKE_GENERATOR STREQUAL "FASTBuild")
+ list(APPEND _picky_enable
+ -Wno-gnu-line-marker # clang 15.0 appleclang 14.0.3
+ )
+ endif()
+ endif()
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) OR
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0))
list(APPEND _picky_enable
@@ -244,20 +251,22 @@
-Wno-format-signedness # clang 19.1 gcc 5.1 appleclang 17.0 # In clang-cl enums are signed ints by default
)
endif()
- if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 21.1)
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 21.1) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 26.4))
list(APPEND _picky_enable
- -Warray-compare # clang 20.1 gcc 12.0 appleclang ?
- -Wc++-hidden-decl # clang 21.1 appleclang ?
- -Wno-implicit-void-ptr-cast # clang 21.1 appleclang ?
- -Wtentative-definition-compat # clang 21.1 appleclang ?
+ -Warray-compare # clang 20.1 gcc 12.0 appleclang 26.4
+ -Wc++-hidden-decl # clang 21.1 appleclang 26.4
+ -Wjump-misses-init # clang 21.1 gcc 4.5 appleclang 26.4
+ -Wno-implicit-void-ptr-cast # clang 21.1 appleclang 26.4
+ -Wtentative-definition-compat # clang 21.1 appleclang 26.4
)
if(WIN32)
list(APPEND _picky_enable
- -Wno-c++-keyword # clang 21.1 appleclang ? # `wchar_t` triggers it on Windows
+ -Wno-c++-keyword # clang 21.1 appleclang 26.4 # `wchar_t` triggers it on Windows
)
else()
list(APPEND _picky_enable
- -Wc++-keyword # clang 21.1 appleclang ?
+ -Wc++-keyword # clang 21.1 appleclang 26.4
)
endif()
endif()
@@ -276,7 +285,7 @@
endif()
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4.5)
list(APPEND _picky_enable
- -Wjump-misses-init # gcc 4.5
+ -Wjump-misses-init # clang 21.1 gcc 4.5 appleclang 26.4
)
if(MINGW)
list(APPEND _picky_enable
@@ -287,23 +296,23 @@
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4.8)
list(APPEND _picky_enable
-Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.1
- -Wformat=2 # clang 3.0 gcc 4.8
+ -Wformat=2 # clang 2.7 gcc 4.8
-Wtrampolines # gcc 4.6
)
endif()
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.0)
list(APPEND _picky_enable
- -Warray-bounds=2 # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
+ -Warray-bounds=2 # clang 2.9 gcc 5.0 (clang default: -Warray-bounds)
-Wno-format-signedness # clang 19.1 gcc 5.1 appleclang 17.0
)
endif()
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)
list(APPEND _picky_enable
-Wduplicated-cond # gcc 6.0
- -Wnull-dereference # clang 3.0 gcc 6.0 (clang default)
+ -Wnull-dereference # clang 2.9 gcc 6.0 (clang default)
-fdelete-null-pointer-checks
-Wshift-negative-value # clang 3.7 gcc 6.0 (clang default)
- -Wshift-overflow=2 # clang 3.0 gcc 6.0 (clang default: -Wshift-overflow)
+ -Wshift-overflow=2 # clang 2.9 gcc 6.0 (clang default: -Wshift-overflow)
-Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
)
endif()
@@ -324,7 +333,7 @@
endif()
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)
list(APPEND _picky_enable
- -Warray-compare # clang 20.0 gcc 12.0 appleclang ?
+ -Warray-compare # clang 20.1 gcc 12.0 appleclang 26.4
-Wenum-int-mismatch # gcc 13.0
-Wxor-used-as-pow # clang 10.0 gcc 13.0 appleclang 12.0
)
@@ -388,7 +397,7 @@
list(APPEND _picky "-Wno-conversion") # Avoid false positives
endif()
endif()
- elseif(MSVC AND MSVC_VERSION LESS_EQUAL 1944) # Skip for untested/unreleased newer versions
+ elseif(MSVC AND MSVC_VERSION LESS_EQUAL 1950) # Skip for untested/unreleased newer versions
list(APPEND _picky "-Wall")
list(APPEND _picky "-wd4061") # enumerator 'A' in switch of enum 'B' is not explicitly handled by a case label
list(APPEND _picky "-wd4191") # 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)(void)'
@@ -397,12 +406,11 @@
list(APPEND _picky "-wd4548") # expression before comma has no effect; expected expression with side-effect (in FD_SET())
list(APPEND _picky "-wd4574") # 'M' is defined to be '0': did you mean to use '#if M'? (in ws2tcpip.h)
list(APPEND _picky "-wd4668") # 'M' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' (in winbase.h)
- list(APPEND _picky "-wd4710") # 'snprintf': function not inlined
+ list(APPEND _picky "-wd4710") # 'fprintf'/'printf'/'sscanf': function not inlined (in tests, with VS2022+ Release)
list(APPEND _picky "-wd4711") # function 'A' selected for automatic inline expansion
# volatile access of '<expression>' is subject to /volatile:<iso|ms> setting;
# consider using __iso_volatile_load/store intrinsic functions (ARM64)
list(APPEND _picky "-wd4746")
- list(APPEND _picky "-wd4774") # 'snprintf': format string expected in argument 3 is not a string literal
list(APPEND _picky "-wd4820") # 'A': 'N' bytes padding added after data member 'B'
if(MSVC_VERSION GREATER_EQUAL 1900)
list(APPEND _picky "-wd5045") # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
@@ -428,6 +436,19 @@
endforeach()
endif()
+if(CMAKE_C_STANDARD STREQUAL 90 AND CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4.2)
+ list(APPEND _picky "-Wno-c99-extensions") # Avoid: warning: '_Bool' is a C99 extension
+ endif()
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1)
+ list(APPEND _picky "-Wno-comma") # Just silly
+ endif()
+endif()
+
+if(DOS AND CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)
+ list(APPEND _picky "-Wno-arith-conversion") # Avoid warnings in DJGPP's built-in FD_SET() macro
+endif()
+
if(_picky_nocheck OR _picky)
set(_picky_tmp "${_picky_nocheck}" "${_picky}")
string(REPLACE ";" " " _picky_tmp "${_picky_tmp}")
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index efa28b7..f86a6aa 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -60,6 +60,10 @@
list(REMOVE_DUPLICATES _cmake_property_list)
list(REMOVE_ITEM _cmake_property_list "")
list(APPEND _cmake_property_list "INTERFACE_LIBCURL_PC_MODULES")
+ get_target_property(_target_imported ${_target} IMPORTED)
+ if(NOT _target_imported)
+ list(REMOVE_ITEM _cmake_property_list "LOCATION" "LOCATION_<CONFIG>" "MACOSX_PACKAGE_LOCATION" "VS_DEPLOYMENT_LOCATION")
+ endif()
foreach(_prop IN LISTS _cmake_property_list)
if(_prop MATCHES "<CONFIG>")
foreach(_config IN ITEMS "DEBUG" "RELEASE" "MINSIZEREL" "RELWITHDEBINFO")
diff --git a/Utilities/cmcurl/CMake/curl-config.in.cmake b/Utilities/cmcurl/CMake/curl-config.in.cmake
index 7f346c8..4e7c29f 100644
--- a/Utilities/cmcurl/CMake/curl-config.in.cmake
+++ b/Utilities/cmcurl/CMake/curl-config.in.cmake
@@ -39,9 +39,21 @@
else()
find_dependency(OpenSSL)
endif()
+ # Define lib duplicate to fixup lib order for GCC binutils ld in static builds
+ if(TARGET OpenSSL::Crypto AND NOT TARGET CURL::OpenSSL_Crypto)
+ add_library(CURL::OpenSSL_Crypto INTERFACE IMPORTED)
+ get_target_property(_curl_libname OpenSSL::Crypto LOCATION)
+ set_target_properties(CURL::OpenSSL_Crypto PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
+ endif()
endif()
if("@HAVE_LIBZ@")
find_dependency(ZLIB "@ZLIB_VERSION_MAJOR@")
+ # Define lib duplicate to fixup lib order for GCC binutils ld in static builds
+ if(TARGET ZLIB::ZLIB AND NOT TARGET CURL::ZLIB)
+ add_library(CURL::ZLIB INTERFACE IMPORTED)
+ get_target_property(_curl_libname ZLIB::ZLIB LOCATION)
+ set_target_properties(CURL::ZLIB PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
+ endif()
endif()
set(_curl_cmake_module_path_save ${CMAKE_MODULE_PATH})
@@ -50,95 +62,96 @@
set(_curl_libs "")
if("@HAVE_BROTLI@")
- find_dependency(Brotli)
+ find_dependency(Brotli MODULE)
list(APPEND _curl_libs CURL::brotli)
endif()
if("@USE_ARES@")
- find_dependency(Cares)
+ find_dependency(Cares MODULE)
list(APPEND _curl_libs CURL::cares)
endif()
if("@HAVE_GSSAPI@")
- find_dependency(GSS)
+ find_dependency(GSS MODULE)
list(APPEND _curl_libs CURL::gss)
endif()
if("@USE_BACKTRACE@")
- find_dependency(Libbacktrace)
+ find_dependency(Libbacktrace MODULE)
list(APPEND _curl_libs CURL::libbacktrace)
endif()
if("@USE_GSASL@")
- find_dependency(Libgsasl)
+ find_dependency(Libgsasl MODULE)
list(APPEND _curl_libs CURL::libgsasl)
endif()
if(NOT "@USE_WIN32_LDAP@" AND NOT "@CURL_DISABLE_LDAP@")
- find_dependency(LDAP)
+ find_dependency(LDAP MODULE)
list(APPEND _curl_libs CURL::ldap)
endif()
if("@HAVE_LIBIDN2@")
- find_dependency(Libidn2)
+ find_dependency(Libidn2 MODULE)
list(APPEND _curl_libs CURL::libidn2)
endif()
if("@USE_LIBPSL@")
- find_dependency(Libpsl)
+ find_dependency(Libpsl MODULE)
list(APPEND _curl_libs CURL::libpsl)
endif()
if("@USE_LIBRTMP@")
- find_dependency(Librtmp)
+ find_dependency(Librtmp MODULE)
list(APPEND _curl_libs CURL::librtmp)
endif()
if("@USE_LIBSSH@")
- find_dependency(Libssh)
+ find_dependency(Libssh MODULE)
list(APPEND _curl_libs CURL::libssh)
endif()
if("@USE_LIBSSH2@")
- find_dependency(Libssh2)
+ find_dependency(Libssh2 MODULE)
list(APPEND _curl_libs CURL::libssh2)
endif()
if("@USE_LIBUV@")
- find_dependency(Libuv)
+ find_dependency(Libuv MODULE)
list(APPEND _curl_libs CURL::libuv)
endif()
if("@USE_MBEDTLS@")
- find_dependency(MbedTLS)
+ find_dependency(MbedTLS MODULE)
list(APPEND _curl_libs CURL::mbedtls)
endif()
if("@USE_NGHTTP2@")
- find_dependency(NGHTTP2)
+ find_dependency(NGHTTP2 MODULE)
list(APPEND _curl_libs CURL::nghttp2)
endif()
if("@USE_NGHTTP3@")
- find_dependency(NGHTTP3)
+ find_dependency(NGHTTP3 MODULE)
list(APPEND _curl_libs CURL::nghttp3)
endif()
if("@USE_NGTCP2@")
- find_dependency(NGTCP2)
+ find_dependency(NGTCP2 MODULE)
list(APPEND _curl_libs CURL::ngtcp2)
endif()
if("@USE_GNUTLS@")
- find_dependency(GnuTLS)
+ find_dependency(GnuTLS MODULE)
list(APPEND _curl_libs CURL::gnutls)
- find_dependency(Nettle)
+ find_dependency(Nettle MODULE)
list(APPEND _curl_libs CURL::nettle)
endif()
if("@USE_QUICHE@")
- find_dependency(Quiche)
+ find_dependency(Quiche MODULE)
list(APPEND _curl_libs CURL::quiche)
endif()
if("@USE_RUSTLS@")
- find_dependency(Rustls)
+ find_dependency(Rustls MODULE)
list(APPEND _curl_libs CURL::rustls)
endif()
if("@USE_WOLFSSL@")
- find_dependency(WolfSSL)
+ find_dependency(WolfSSL MODULE)
list(APPEND _curl_libs CURL::wolfssl)
endif()
if("@HAVE_ZSTD@")
- find_dependency(Zstd)
+ find_dependency(Zstd MODULE)
list(APPEND _curl_libs CURL::zstd)
endif()
set(CMAKE_MODULE_PATH ${_curl_cmake_module_path_save})
-if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND WIN32 AND NOT TARGET CURL::win32_winsock)
+# Define lib duplicate to fixup lib order for GCC binutils ld in static builds
+if(WIN32 AND NOT TARGET CURL::win32_winsock)
add_library(CURL::win32_winsock INTERFACE IMPORTED)
set_target_properties(CURL::win32_winsock PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32")
endif()
@@ -163,9 +176,11 @@
if(NOT _has_CMP0099 AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.13 AND _curl_libs)
set(_curl_libdirs "")
foreach(_curl_lib IN LISTS _curl_libs)
- get_target_property(_curl_libdir "${_curl_lib}" INTERFACE_LINK_DIRECTORIES)
- if(_curl_libdir)
- list(APPEND _curl_libdirs "${_curl_libdir}")
+ if(TARGET "${_curl_lib}")
+ get_target_property(_curl_libdir "${_curl_lib}" INTERFACE_LINK_DIRECTORIES)
+ if(_curl_libdir)
+ list(APPEND _curl_libdirs "${_curl_libdir}")
+ endif()
endif()
endforeach()
if(_curl_libdirs)
diff --git a/Utilities/cmcurl/CMake/unix-cache.cmake b/Utilities/cmcurl/CMake/unix-cache.cmake
index eded7d9..f358a47 100644
--- a/Utilities/cmcurl/CMake/unix-cache.cmake
+++ b/Utilities/cmcurl/CMake/unix-cache.cmake
@@ -172,7 +172,6 @@
endif()
set(HAVE_LOCALE_H 1)
set(HAVE_LOCALTIME_R 1)
-set(HAVE_LONGLONG 1)
if(APPLE)
set(HAVE_MACH_ABSOLUTE_TIME 1)
endif()
@@ -182,7 +181,6 @@
else()
set(HAVE_MEMRCHR 1)
endif()
-set(HAVE_MSG_NOSIGNAL 1)
set(HAVE_NETDB_H 1)
if(ANDROID)
set(HAVE_NETINET_IN6_H 1)
@@ -228,12 +226,6 @@
endif()
set(HAVE_SENDMSG 1)
set(HAVE_SETLOCALE 1)
-if(CYGWIN OR
- CMAKE_SYSTEM_NAME STREQUAL "Linux")
- set(HAVE_SETMODE 0)
-else()
- set(HAVE_SETMODE 1)
-endif()
set(HAVE_SETRLIMIT 1)
set(HAVE_SETSOCKOPT_SO_NONBLOCK 0)
set(HAVE_SIGACTION 1)
@@ -247,11 +239,10 @@
set(HAVE_SOCKETPAIR 1)
set(HAVE_STDATOMIC_H 1)
set(HAVE_STDBOOL_H 1)
-set(HAVE_STDDEF_H 1)
-set(HAVE_STDINT_H 1)
+set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
+set(HAVE_STDINT_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STRCASECMP 1)
set(HAVE_STRCMPI 0)
-set(HAVE_STRDUP 1)
set(HAVE_STRERROR_R 1)
set(HAVE_STRICMP 0)
set(HAVE_STRINGS_H 1)
@@ -311,8 +302,5 @@
set(HAVE_UTIMES 1)
set(HAVE_UTIME_H 1)
set(HAVE_WRITABLE_ARGV 1)
-if(CYGWIN)
- set(HAVE__SETMODE 1)
-endif()
set(STDC_HEADERS 1)
set(USE_UNIX_SOCKETS 1)
diff --git a/Utilities/cmcurl/CMake/win32-cache.cmake b/Utilities/cmcurl/CMake/win32-cache.cmake
index e704d21..77535a6 100644
--- a/Utilities/cmcurl/CMake/win32-cache.cmake
+++ b/Utilities/cmcurl/CMake/win32-cache.cmake
@@ -33,7 +33,6 @@
set(HAVE_GETTIMEOFDAY 1)
set(HAVE_LIBGEN_H 1)
set(HAVE_OPENDIR 1)
- set(HAVE_SNPRINTF 1)
set(HAVE_STDBOOL_H 1)
set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STDINT_H 1) # detected by CMake internally in check_type_size()
@@ -60,11 +59,6 @@
set(HAVE_STDBOOL_H 0)
endif()
set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
- if(MSVC_VERSION GREATER_EQUAL 1900)
- set(HAVE_SNPRINTF 1)
- else()
- set(HAVE_SNPRINTF 0)
- endif()
set(HAVE_BASENAME 0)
endif()
endif()
@@ -125,7 +119,6 @@
set(HAVE_LOCALE_H 1)
set(HAVE_LOCALTIME_R 0)
set(HAVE_MEMRCHR 0)
-set(HAVE_MSG_NOSIGNAL 0)
set(HAVE_NETDB_H 0)
set(HAVE_NETINET_IN6_H 0)
set(HAVE_NETINET_IN_H 0)
@@ -144,7 +137,6 @@
set(HAVE_SENDMMSG 0)
set(HAVE_SENDMSG 0)
set(HAVE_SETLOCALE 1)
-set(HAVE_SETMODE 1)
set(HAVE_SETRLIMIT 0)
set(HAVE_SETSOCKOPT_SO_NONBLOCK 0)
set(HAVE_SIGACTION 0)
@@ -154,7 +146,6 @@
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
set(HAVE_SOCKET 1)
set(HAVE_SOCKETPAIR 0)
-set(HAVE_STRDUP 1)
set(HAVE_STRERROR_R 0)
set(HAVE_STROPTS_H 0)
set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
@@ -174,7 +165,6 @@
set(HAVE_TIME_T_UNSIGNED 0)
set(HAVE_UTIME 1)
set(HAVE_UTIMES 0)
-set(HAVE__SETMODE 1)
set(STDC_HEADERS 1)
# Types and sizes
@@ -185,7 +175,6 @@
if(MINGW OR MSVC)
curl_prefill_type_size("INT" 4)
curl_prefill_type_size("LONG" 4)
- curl_prefill_type_size("LONG_LONG" 8)
curl_prefill_type_size("__INT64" 8)
curl_prefill_type_size("CURL_OFF_T" 8)
curl_prefill_type_size("CURL_SOCKET_T" ${CMAKE_SIZEOF_VOID_P})
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 2c6a6e6..017c6ea 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -8,6 +8,7 @@
set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS ON)
set(BUILD_STATIC_CURL OFF)
+set(CURL_BUILD_EVERYTHING OFF)
set(CURL_CA_SEARCH_SAFE OFF)
set(CURL_USE_GSASL OFF)
set(CURL_USE_GSSAPI OFF)
@@ -192,7 +193,7 @@
get_property(_cache_var_type CACHE ${_cache_var} PROPERTY TYPE)
get_property(_cache_var_value CACHE ${_cache_var} PROPERTY VALUE)
if(_cache_var_type STREQUAL "UNINITIALIZED")
- set(_cache_var_type)
+ set(_cache_var_type "")
else()
set(_cache_var_type ":${_cache_var_type}")
endif()
@@ -298,6 +299,9 @@
if(CMAKE_CROSSCOMPILING)
string(APPEND _target_flags " CROSS")
endif()
+if(CMAKE_C_STANDARD)
+ string(APPEND _target_flags " C${CMAKE_C_STANDARD}")
+endif()
if(0) # XXX(cmake): not needed for build within cmake
message(STATUS "CMake platform flags:${_target_flags}")
endif() # XXX(cmake): end
@@ -314,6 +318,10 @@
set(CURL_OS "\"${CMAKE_SYSTEM_NAME}\"")
endif()
+if(CURL_PATCHSTAMP)
+ set(CURL_PATCHSTAMP "\"${CURL_PATCHSTAMP}\"")
+endif()
+
set(LIB_NAME "libcurl")
set(EXE_NAME "curl")
@@ -343,6 +351,7 @@
option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF)
option(ENABLE_ARES "Enable c-ares support" OFF)
option(CURL_DISABLE_INSTALL "Disable installation targets" OFF)
+option(CURL_BUILD_EVERYTHING "Build optional build targets (examples, tests) by default" OFF)
if(WIN32)
option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF)
@@ -359,14 +368,15 @@
if(0) # XXX(cmake): not needed for build within cmake
# Apply to all feature checks
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")
- if(MSVC)
- list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_CRT_NONSTDC_NO_DEPRECATE") # for strdup() detection
- endif()
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
if(CURL_TARGET_WINDOWS_VERSION)
- set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
- list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}") # Apply to all feature checks
+ if(CURL_TARGET_WINDOWS_VERSION MATCHES "^0x[0-9a-fA-F]+$")
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}") # Apply to all feature checks
+ else()
+ message(WARNING "CURL_TARGET_WINDOWS_VERSION value '${CURL_TARGET_WINDOWS_VERSION}' is not a valid hex string.")
+ endif()
endif()
endif() # XXX(cmake): end
@@ -375,7 +385,7 @@
if(HAVE_WIN32_WINNT)
string(REGEX MATCH "_WIN32_WINNT=0x[0-9a-fA-F]+" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}")
string(REGEX REPLACE "_WIN32_WINNT=" "" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}")
- string(REGEX REPLACE "0x([0-9a-f][0-9a-f][0-9a-f])$" "0x0\\1" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}") # pad to 4 digits
+ string(REGEX REPLACE "0x([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])$" "0x0\\1" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}") # pad to 4 digits
string(TOLOWER "${CURL_TEST_OUTPUT}" HAVE_WIN32_WINNT)
message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
endif()
@@ -412,8 +422,6 @@
endif()
option(ENABLE_THREADED_RESOLVER "Enable threaded DNS lookup" ${_enable_threaded_resolver_default})
endif()
-
-include(PickyWarnings)
endif() # XXX(cmake): end
if(CYGWIN OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "GNU")
@@ -425,35 +433,29 @@
if(ENABLE_DEBUG)
message(WARNING "This curl build is Debug-enabled and insecure, do not use in production.")
endif()
-option(ENABLE_CURLDEBUG "Enable TrackMemory debug feature" ${ENABLE_DEBUG})
set(CURL_DEBUG_MACROS "")
if(ENABLE_DEBUG)
list(APPEND CURL_DEBUG_MACROS "DEBUGBUILD")
endif()
-if(ENABLE_CURLDEBUG)
- list(APPEND CURL_DEBUG_MACROS "CURLDEBUG")
-endif()
if(0) # XXX(cmake): not needed for build within cmake
option(CURL_CLANG_TIDY "Run the build through clang-tidy" OFF)
if(CURL_CLANG_TIDY)
- set(CMAKE_UNITY_BUILD OFF) # clang-tidy is not looking into #included sources, thus not compatible with unity builds.
- set(CURL_DISABLE_TYPECHECK ON) # to improve performance and avoid potential interference.
- set(_tidy_checks "")
- list(APPEND _tidy_checks "-clang-analyzer-security.insecureAPI.bzero") # for FD_ZERO() (seen on macOS)
- list(APPEND _tidy_checks "-clang-analyzer-optin.performance.Padding")
- list(APPEND _tidy_checks "-clang-analyzer-security.ArrayBound") # false positives with clang-tidy v21.1.0
- list(APPEND _tidy_checks "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling")
- string(REPLACE ";" "," _tidy_checks "${_tidy_checks}")
find_program(CLANG_TIDY NAMES "clang-tidy" REQUIRED)
- set(CMAKE_C_CLANG_TIDY "${CLANG_TIDY}" "-checks=${_tidy_checks}" "-quiet")
- unset(_tidy_checks)
+ if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(PICKY_COMPILER OFF) # Do a best effort and skip passing non-clang warning options to clang-tidy.
+ # This lets through warning options enabled via CURL_WERROR=ON, affecting lib and src.
+ endif()
+ set(CURL_DISABLE_TYPECHECK ON) # to improve performance and avoid potential interference.
+ set(CMAKE_C_CLANG_TIDY "${CLANG_TIDY}")
+ list(APPEND CMAKE_C_CLANG_TIDY "--config-file=${PROJECT_SOURCE_DIR}/.clang-tidy.yml")
if(CURL_WERROR)
list(APPEND CMAKE_C_CLANG_TIDY "--warnings-as-errors=*")
endif()
if(CURL_CLANG_TIDYFLAGS)
- list(APPEND CMAKE_C_CLANG_TIDY ${CURL_CLANG_TIDYFLAGS})
+ string(REPLACE " " ";" _tidy_flags_list "${CURL_CLANG_TIDYFLAGS}")
+ list(APPEND CMAKE_C_CLANG_TIDY ${_tidy_flags_list})
endif()
endif()
@@ -477,6 +479,42 @@
endif()
endif()
+include(PickyWarnings)
+
+set(CURL_CFLAGS "") # C flags set for libcurl and curl tool (aka public binaries) only
+
+option(CURL_DROP_UNUSED "Drop unused code and data from built binaries" OFF)
+if(CURL_DROP_UNUSED)
+ if(APPLE)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
+ set_property(DIRECTORY APPEND PROPERTY LINK_OPTIONS "-Wl,-dead_strip")
+ else()
+ set_property(DIRECTORY APPEND PROPERTY LINK_FLAGS "-Wl,-dead_strip")
+ endif()
+ elseif(MSVC) # Options below are toolchain defaults in Release configurations.
+ # This option does not seem to have an effect with VS2010:
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
+ set_property(DIRECTORY APPEND PROPERTY LINK_OPTIONS "-OPT:REF")
+ else()
+ set_property(DIRECTORY APPEND PROPERTY LINK_FLAGS "-OPT:REF")
+ endif()
+ # Optional, but reduces binary size further, with the cost of larger objects/static libraries:
+ list(APPEND CURL_CFLAGS "-Gy")
+ elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ if(WIN32)
+ # To make -Wl,--gc-sections work on Windows: https://sourceware.org/bugzilla/show_bug.cgi?id=11539
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "-fno-asynchronous-unwind-tables")
+ endif()
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
+ set_property(DIRECTORY APPEND PROPERTY LINK_OPTIONS "-Wl,--gc-sections")
+ else()
+ set_property(DIRECTORY APPEND PROPERTY LINK_FLAGS "-Wl,--gc-sections")
+ endif()
+ # Optional, but reduces binary size further, with the cost of larger objects/static libraries:
+ list(APPEND CURL_CFLAGS "-ffunction-sections" "-fdata-sections")
+ endif()
+endif()
+
# For debug libs and exes, add "-d" postfix
if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "-d")
@@ -538,7 +576,7 @@
if(ENABLE_ARES)
set(USE_ARES 1)
- find_package(Cares REQUIRED)
+ find_package(Cares MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::cares)
endif()
@@ -644,6 +682,11 @@
option(CURL_DISABLE_VERBOSE_STRINGS "Disable verbose strings" OFF)
mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
+if(CURL_DISABLE_TYPECHECK)
+ # Set it via the command-line to make it apply to examples also.
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "CURL_DISABLE_TYPECHECK")
+endif()
+
if(CURL_DISABLE_HTTP)
set(CURL_DISABLE_ALTSVC ON)
set(CURL_DISABLE_HSTS ON)
@@ -672,6 +715,7 @@
set(CURL_DISABLE_SMTP ON)
set(CURL_DISABLE_TELNET ON)
set(CURL_DISABLE_TFTP ON)
+ set(CURL_DISABLE_WEBSOCKETS ON)
endif()
if(WINDOWS_STORE)
@@ -679,6 +723,8 @@
endif()
if(0) # XXX(cmake): not needed for build within cmake
+option(CURL_LINT "Run lint checks while building" OFF)
+
find_package(Perl)
if(PERL_EXECUTABLE)
@@ -692,6 +738,18 @@
COMMAND "${PERL_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/firefox-db2pem.sh" "lib/ca-bundle.crt"
DEPENDS "${PROJECT_SOURCE_DIR}/scripts/firefox-db2pem.sh"
)
+ add_custom_target(curl-lint
+ COMMENT "Running lint checks" VERBATIM USES_TERMINAL
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ COMMAND "${PERL_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/checksrc-all.pl"
+ COMMAND "${PERL_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/spacecheck.pl"
+ DEPENDS
+ "${PROJECT_SOURCE_DIR}/scripts/checksrc-all.pl" "${PROJECT_SOURCE_DIR}/scripts/checksrc.pl"
+ "${PROJECT_SOURCE_DIR}/scripts/spacecheck.pl"
+ )
+ if(CURL_LINT)
+ set_target_properties(curl-lint PROPERTIES EXCLUDE_FROM_ALL FALSE)
+ endif()
endif()
option(BUILD_LIBCURL_DOCS "Build libcurl man pages" ON)
@@ -727,6 +785,7 @@
include(CheckCSourceCompiles)
option(_CURL_PREFILL "Fast-track known feature detection results (Windows, some Apple)" "${WIN32}")
+mark_as_advanced(_CURL_PREFILL)
if(_CURL_PREFILL)
if(WIN32)
include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/win32-cache.cmake")
@@ -857,11 +916,6 @@
set(_openssl_default ON)
endif()
cmake_dependent_option(CURL_USE_OPENSSL "Enable OpenSSL for SSL/TLS" ${_openssl_default} CURL_ENABLE_SSL OFF)
-option(USE_OPENSSL_QUIC "Use OpenSSL and nghttp3 libraries for HTTP/3 support" OFF)
-if(USE_OPENSSL_QUIC AND NOT CURL_USE_OPENSSL)
- message(WARNING "OpenSSL QUIC has been requested, but without enabling OpenSSL. Will not enable QUIC.")
- set(USE_OPENSSL_QUIC OFF)
-endif()
option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)
endif() # XXX(cmake): end
@@ -901,9 +955,9 @@
if(NOT CURL_USE_OPENSSL AND NOT CURL_USE_GNUTLS)
message(FATAL_ERROR "Apple SecTrust is only supported with Openssl/GnuTLS")
endif()
- find_library(COREFOUNDATION_FRAMEWORK NAMES "Security")
- mark_as_advanced(COREFOUNDATION_FRAMEWORK)
- if(NOT COREFOUNDATION_FRAMEWORK)
+ find_library(SECURITY_FRAMEWORK NAMES "Security")
+ mark_as_advanced(SECURITY_FRAMEWORK)
+ if(NOT SECURITY_FRAMEWORK)
message(FATAL_ERROR "Security framework not found")
endif()
list(APPEND CURL_LIBS "-framework Security")
@@ -944,7 +998,6 @@
# Depend on OpenSSL via imported targets. This allows our dependents to
# get our dependencies transitively.
list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto)
- set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_LIBCURL_PC_MODULES "openssl")
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl")
set(_valid_default_ssl_backend TRUE)
@@ -981,6 +1034,9 @@
endif()
if(HAVE_BORINGSSL)
+ if(BORINGSSL_VERSION)
+ set(CURL_BORINGSSL_VERSION "\"${BORINGSSL_VERSION}\"")
+ endif()
set(_openssl "BoringSSL")
elseif(HAVE_AWSLC)
set(_openssl "AWS-LC")
@@ -994,7 +1050,7 @@
endif()
if(CURL_USE_MBEDTLS)
- find_package(MbedTLS REQUIRED)
+ find_package(MbedTLS MODULE REQUIRED)
if(MBEDTLS_VERSION VERSION_LESS 3.2.0)
message(FATAL_ERROR "mbedTLS v3.2.0 or newer is required.")
endif()
@@ -1019,7 +1075,7 @@
endif()
if(CURL_USE_WOLFSSL)
- find_package(WolfSSL REQUIRED)
+ find_package(WolfSSL MODULE REQUIRED)
set(_ssl_enabled ON)
set(USE_WOLFSSL ON)
list(APPEND CURL_LIBS CURL::wolfssl)
@@ -1028,12 +1084,18 @@
set(_valid_default_ssl_backend TRUE)
endif()
set(_curl_ca_bundle_supported TRUE)
+
+ if(USE_OPENSSL AND WOLFSSL_VERSION VERSION_LESS 5.7.6)
+ message(FATAL_ERROR "wolfSSL 5.7.6 or newer is required to coexist with OpenSSL.")
+ endif()
+
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "WOLFSSL_OPTIONS_IGNORE_SYS")
endif()
if(CURL_USE_GNUTLS)
- find_package(GnuTLS REQUIRED)
+ find_package(GnuTLS MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::gnutls)
- find_package(Nettle REQUIRED)
+ find_package(Nettle MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::nettle)
set(_ssl_enabled ON)
set(USE_GNUTLS ON)
@@ -1054,7 +1116,7 @@
endif()
if(CURL_USE_RUSTLS)
- find_package(Rustls REQUIRED)
+ find_package(Rustls MODULE REQUIRED)
set(_ssl_enabled ON)
set(USE_RUSTLS ON)
list(APPEND CURL_LIBS CURL::rustls)
@@ -1094,7 +1156,6 @@
# get our dependencies transitively.
if(CMAKE_USE_SYSTEM_ZLIB)
list(APPEND CURL_LIBS ZLIB::ZLIB)
- set_target_properties(ZLIB::ZLIB PROPERTIES INTERFACE_LIBCURL_PC_MODULES "zlib")
else()
list(APPEND CURL_LIBS cmzlib)
endif()
@@ -1137,6 +1198,7 @@
endif()
if(USE_WOLFSSL)
list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::wolfssl)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DWOLFSSL_OPTIONS_IGNORE_SYS")
if(HAVE_LIBZ)
list(APPEND CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB) # Public wolfSSL headers also require zlib headers
endif()
@@ -1155,7 +1217,7 @@
# Ensure that OpenSSL (or fork) or wolfSSL actually supports QUICTLS API.
macro(curl_openssl_check_quic)
- if(USE_OPENSSL AND NOT USE_OPENSSL_QUIC)
+ if(USE_OPENSSL)
if(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.5.0)
if(NOT DEFINED HAVE_SSL_SET_QUIC_TLS_CBS)
curl_openssl_check_exists("SSL_set_quic_tls_cbs" HAVE_SSL_SET_QUIC_TLS_CBS)
@@ -1236,7 +1298,7 @@
option(USE_NGHTTP2 "Use nghttp2 library" ON)
if(USE_NGHTTP2)
- find_package(NGHTTP2)
+ find_package(NGHTTP2 MODULE)
if(NGHTTP2_FOUND)
list(APPEND CURL_LIBS CURL::nghttp2)
else()
@@ -1250,33 +1312,33 @@
message(FATAL_ERROR "MultiSSL cannot be enabled with HTTP/3 and vice versa.")
elseif(USE_OPENSSL OR USE_WOLFSSL)
if(USE_WOLFSSL)
- find_package(NGTCP2 REQUIRED COMPONENTS "wolfSSL")
+ find_package(NGTCP2 MODULE REQUIRED COMPONENTS "wolfSSL")
elseif(HAVE_BORINGSSL OR HAVE_AWSLC)
- find_package(NGTCP2 REQUIRED COMPONENTS "BoringSSL")
- elseif(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.5.0 AND NOT USE_OPENSSL_QUIC)
- find_package(NGTCP2 REQUIRED COMPONENTS "ossl")
+ find_package(NGTCP2 MODULE REQUIRED COMPONENTS "BoringSSL")
+ elseif(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.5.0)
+ find_package(NGTCP2 MODULE REQUIRED COMPONENTS "ossl")
if(NGTCP2_VERSION VERSION_LESS 1.12.0)
message(FATAL_ERROR "ngtcp2 1.12.0 or upper required for OpenSSL")
endif()
set(OPENSSL_QUIC_API2 1)
elseif(HAVE_LIBRESSL)
- find_package(NGTCP2 COMPONENTS "LibreSSL")
+ find_package(NGTCP2 MODULE COMPONENTS "LibreSSL")
if(NOT NGTCP2_FOUND)
- find_package(NGTCP2 REQUIRED COMPONENTS "quictls") # for ngtcp2 <1.15.0
+ find_package(NGTCP2 MODULE REQUIRED COMPONENTS "quictls") # for ngtcp2 <1.15.0
endif()
else()
- find_package(NGTCP2 REQUIRED COMPONENTS "quictls")
+ find_package(NGTCP2 MODULE REQUIRED COMPONENTS "quictls")
set(_openssl "quictls")
endif()
curl_openssl_check_quic()
elseif(USE_GNUTLS)
- find_package(NGTCP2 REQUIRED "GnuTLS")
+ find_package(NGTCP2 MODULE REQUIRED "GnuTLS")
else()
message(FATAL_ERROR "ngtcp2 requires a supported TLS-backend")
endif()
list(APPEND CURL_LIBS CURL::ngtcp2)
- find_package(NGHTTP3 REQUIRED)
+ find_package(NGHTTP3 MODULE REQUIRED)
set(USE_NGHTTP3 ON)
list(APPEND CURL_LIBS CURL::nghttp3)
endif()
@@ -1288,7 +1350,7 @@
elseif(CURL_WITH_MULTI_SSL)
message(FATAL_ERROR "MultiSSL cannot be enabled with HTTP/3 and vice versa.")
endif()
- find_package(Quiche REQUIRED)
+ find_package(Quiche MODULE REQUIRED)
if(NOT HAVE_BORINGSSL)
message(FATAL_ERROR "quiche requires BoringSSL")
endif()
@@ -1302,19 +1364,6 @@
endif()
endif()
-if(USE_OPENSSL_QUIC)
- if(USE_NGTCP2 OR USE_QUICHE)
- message(FATAL_ERROR "Only one HTTP/3 backend can be selected")
- elseif(CURL_WITH_MULTI_SSL)
- message(FATAL_ERROR "MultiSSL cannot be enabled with HTTP/3 and vice versa.")
- endif()
- find_package(OpenSSL 3.3.0 REQUIRED)
-
- find_package(NGHTTP3 REQUIRED)
- set(USE_NGHTTP3 ON)
- list(APPEND CURL_LIBS CURL::nghttp3)
-endif()
-
if(NOT CURL_DISABLE_SRP AND (HAVE_GNUTLS_SRP OR HAVE_OPENSSL_SRP))
set(USE_TLS_SRP 1)
endif()
@@ -1337,7 +1386,7 @@
if(USE_OPENSSL)
list(APPEND CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
endif()
- find_package(LDAP)
+ find_package(LDAP MODULE)
if(LDAP_FOUND)
set(HAVE_LBER_H 1)
set(CURL_LIBS CURL::ldap ${CURL_LIBS})
@@ -1405,7 +1454,7 @@
set(HAVE_IDN2_H OFF)
set(HAVE_LIBIDN2 OFF)
if(USE_LIBIDN2 AND NOT USE_APPLE_IDN AND NOT USE_WIN32_IDN)
- find_package(Libidn2 QUIET)
+ find_package(Libidn2 MODULE QUIET)
if(LIBIDN2_FOUND)
set(CURL_LIBS CURL::libidn2 ${CURL_LIBS})
set(HAVE_IDN2_H 1)
@@ -1418,7 +1467,7 @@
mark_as_advanced(CURL_USE_LIBPSL)
set(USE_LIBPSL OFF)
if(CURL_USE_LIBPSL)
- find_package(Libpsl REQUIRED)
+ find_package(Libpsl MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::libpsl)
set(USE_LIBPSL ON)
endif()
@@ -1428,7 +1477,7 @@
mark_as_advanced(CURL_USE_LIBSSH2)
set(USE_LIBSSH2 OFF)
if(CURL_USE_LIBSSH2)
- find_package(Libssh2)
+ find_package(Libssh2 MODULE)
if(LIBSSH2_FOUND)
set(CURL_LIBS CURL::libssh2 ${CURL_LIBS}) # keep it before TLS-crypto, compression
set(USE_LIBSSH2 ON)
@@ -1439,7 +1488,7 @@
option(CURL_USE_LIBSSH "Use libssh" OFF)
mark_as_advanced(CURL_USE_LIBSSH)
if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
- find_package(Libssh REQUIRED)
+ find_package(Libssh MODULE REQUIRED)
set(CURL_LIBS CURL::libssh ${CURL_LIBS}) # keep it before TLS-crypto, compression
set(USE_LIBSSH ON)
endif()
@@ -1447,7 +1496,7 @@
option(CURL_USE_GSASL "Use libgsasl" OFF)
mark_as_advanced(CURL_USE_GSASL)
if(CURL_USE_GSASL)
- find_package(Libgsasl REQUIRED)
+ find_package(Libgsasl MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::libgsasl)
set(USE_GSASL ON)
endif()
@@ -1456,7 +1505,7 @@
mark_as_advanced(CURL_USE_GSSAPI)
if(CURL_USE_GSSAPI)
- find_package(GSS)
+ find_package(GSS MODULE)
set(HAVE_GSSAPI ${GSS_FOUND})
if(GSS_FOUND)
@@ -1474,15 +1523,15 @@
endif()
# libbacktrace
-option(CURL_USE_LIBBACKTRACE "Use libbacktrace. Requires build with TrackMemory and DWARF debug information." OFF)
+option(CURL_USE_LIBBACKTRACE "Use libbacktrace. Requires debug-enabled build and DWARF debug information." OFF)
if(CURL_USE_LIBBACKTRACE)
- if(NOT ENABLE_CURLDEBUG)
- message(FATAL_ERROR "libbacktrace requires TrackMemory enabled")
+ if(NOT ENABLE_DEBUG)
+ message(FATAL_ERROR "libbacktrace requires debug-enabled build for TrackMemory")
endif()
if(NOT CMAKE_BUILD_TYPE MATCHES "(Debug|RelWithDebInfo)")
message(FATAL_ERROR "libbacktrace requires debug information")
endif()
- find_package(Libbacktrace REQUIRED)
+ find_package(Libbacktrace MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::libbacktrace)
set(USE_BACKTRACE ON)
endif()
@@ -1493,7 +1542,7 @@
if(NOT ENABLE_DEBUG)
message(FATAL_ERROR "Using libuv without debug support enabled is useless")
endif()
- find_package(Libuv REQUIRED)
+ find_package(Libuv MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::libuv)
set(USE_LIBUV ON)
set(HAVE_UV_H ON)
@@ -1501,7 +1550,7 @@
option(USE_LIBRTMP "Enable librtmp from rtmpdump" OFF)
if(USE_LIBRTMP)
- find_package(Librtmp REQUIRED)
+ find_package(Librtmp MODULE REQUIRED)
list(APPEND CURL_LIBS CURL::librtmp)
endif()
@@ -1522,6 +1571,13 @@
#
# CA handling
#
+option(CURL_CA_NATIVE "Use native CA store" OFF)
+if(CURL_CA_NATIVE)
+ set(_curl_disable_ca_search_default ON)
+else()
+ set(_curl_disable_ca_search_default OFF)
+endif()
+
if(_curl_ca_bundle_supported)
set(_ca_opt_desc "Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
@@ -1544,7 +1600,7 @@
unset(CURL_CA_BUNDLE CACHE)
elseif(CURL_CA_BUNDLE STREQUAL "auto")
unset(CURL_CA_BUNDLE CACHE)
- if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST)
+ if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST AND NOT CURL_CA_NATIVE)
set(_curl_ca_bundle_autodetect TRUE)
endif()
else()
@@ -1558,7 +1614,7 @@
unset(CURL_CA_PATH CACHE)
elseif(CURL_CA_PATH STREQUAL "auto")
unset(CURL_CA_PATH CACHE)
- if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST)
+ if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST AND NOT CURL_CA_NATIVE)
set(_curl_ca_path_autodetect TRUE)
endif()
else()
@@ -1616,30 +1672,20 @@
endif() # XXX(cmake): end
if(WIN32)
- option(CURL_DISABLE_CA_SEARCH "Disable unsafe CA bundle search in PATH on Windows" OFF)
+ option(CURL_DISABLE_CA_SEARCH "Disable unsafe CA bundle search in PATH on Windows" ${_curl_disable_ca_search_default})
option(CURL_CA_SEARCH_SAFE "Enable safe CA bundle search (within the curl tool directory) on Windows" OFF)
endif()
+set(CURL_INCLUDES "")
+
# Check for header files
if(WIN32)
list(APPEND CURL_INCLUDES "winsock2.h")
list(APPEND CURL_INCLUDES "ws2tcpip.h")
- if(HAVE_WIN32_WINNT AND HAVE_WIN32_WINNT LESS 0x0501)
- # Windows XP is required for freeaddrinfo, getaddrinfo
- message(FATAL_ERROR "Building for Windows XP or newer is required.")
- endif()
-
- # Pre-fill detection results based on target OS version
- if(_CURL_PREFILL)
- if(NOT HAVE_WIN32_WINNT OR HAVE_WIN32_WINNT LESS 0x0600 OR # older than Windows Vista
- WINDOWS_STORE)
- set(HAVE_IF_NAMETOINDEX 0)
- unset(HAVE_IF_NAMETOINDEX CACHE)
- elseif(MSVC OR MINGW)
- set(HAVE_IF_NAMETOINDEX 1)
- unset(HAVE_IF_NAMETOINDEX CACHE)
- endif()
+ if(HAVE_WIN32_WINNT AND HAVE_WIN32_WINNT LESS 0x0600)
+ # Windows Vista is required for freeaddrinfo, getaddrinfo, if_nametoindex
+ message(FATAL_ERROR "Building for Windows Vista or newer is required.")
endif()
endif()
@@ -1685,7 +1731,6 @@
check_include_file("pwd.h" HAVE_PWD_H)
check_include_file("stdatomic.h" HAVE_STDATOMIC_H)
check_include_file("stdbool.h" HAVE_STDBOOL_H)
-check_include_file("stdint.h" HAVE_STDINT_H)
check_include_file("strings.h" HAVE_STRINGS_H)
check_include_file("stropts.h" HAVE_STROPTS_H)
check_include_file("termio.h" HAVE_TERMIO_H)
@@ -1749,7 +1794,6 @@
check_function_exists("sendmsg" HAVE_SENDMSG)
check_function_exists("sendmmsg" HAVE_SENDMMSG)
check_symbol_exists("select" "${CURL_INCLUDES}" HAVE_SELECT) # proto/bsdsocket.h sys/select.h sys/socket.h
-check_symbol_exists("strdup" "string.h" HAVE_STRDUP)
check_symbol_exists("memrchr" "string.h" HAVE_MEMRCHR)
check_symbol_exists("alarm" "unistd.h" HAVE_ALARM)
check_symbol_exists("fcntl" "fcntl.h" HAVE_FCNTL)
@@ -1787,23 +1831,16 @@
check_function_exists("setlocale" HAVE_SETLOCALE)
check_function_exists("setrlimit" HAVE_SETRLIMIT)
-if(WIN32)
- # include wincrypt.h as a workaround for mingw-w64 __MINGW64_VERSION_MAJOR <= 5 header bug */
- check_symbol_exists("if_nametoindex" "winsock2.h;wincrypt.h;iphlpapi.h" HAVE_IF_NAMETOINDEX) # Windows Vista+ non-UWP */
-else()
+if(NOT WIN32)
check_function_exists("if_nametoindex" HAVE_IF_NAMETOINDEX) # net/if.h
check_function_exists("realpath" HAVE_REALPATH)
check_function_exists("sched_yield" HAVE_SCHED_YIELD)
+ check_function_exists("snprintf" HAVE_SNPRINTF) # to match detection method in ./configure
check_symbol_exists("strcasecmp" "string.h" HAVE_STRCASECMP)
check_symbol_exists("stricmp" "string.h" HAVE_STRICMP)
check_symbol_exists("strcmpi" "string.h" HAVE_STRCMPI)
endif()
-check_function_exists("setmode" HAVE_SETMODE)
-if(WIN32 OR CYGWIN)
- check_function_exists("_setmode" HAVE__SETMODE)
-endif()
-
if(AMIGA)
check_symbol_exists("CloseSocket" "${CURL_INCLUDES}" HAVE_CLOSESOCKET_CAMEL) # sys/socket.h proto/bsdsocket.h
endif()
@@ -1812,11 +1849,6 @@
check_symbol_exists("arc4random" "${CURL_INCLUDES};stdlib.h" HAVE_ARC4RANDOM)
endif()
-if(NOT MSVC)
- check_function_exists("snprintf" HAVE_SNPRINTF) # to match detection method in ./configure
-elseif(MSVC_VERSION GREATER_EQUAL 1900) # Earlier MSVC compilers had faulty snprintf implementations
- check_symbol_exists("snprintf" "stdio.h" HAVE_SNPRINTF) # snprintf may be a compatibility macro, not an exported function
-endif()
if(APPLE)
check_function_exists("mach_absolute_time" HAVE_MACH_ABSOLUTE_TIME)
endif()
@@ -1927,7 +1959,7 @@
{
(void)argc;
argv[0][0] = ' ';
- return (argv[0][0] == ' ')?0:1;
+ return (argv[0][0] == ' ') ? 0 : 1;
}" HAVE_WRITABLE_ARGV)
endif()
endif() # XXX(cmake): end
@@ -1997,15 +2029,27 @@
# list on the linker command-line for some reason. This makes them appear
# before dependencies detected via curl's custom Find modules, and breaks
# linkers sensitive to lib order. There must be a better solution to this.
+# Enable the workaround for all compilers, to make it available when using GCC
+# to consume libcurl, regardless of the compiler used to build libcurl itself.
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
- foreach(_lib IN ITEMS OpenSSL::Crypto ZLIB::ZLIB)
- if(TARGET "${_lib}")
- add_library(CURL::${_lib} INTERFACE IMPORTED)
- get_target_property(_libname "${_lib}" LOCATION)
- set_target_properties(${_lib} PROPERTIES INTERFACE_LINK_LIBRARIES "${_libname}")
- list(APPEND CURL_LIBS ${_lib})
+ if(USE_OPENSSL AND TARGET OpenSSL::Crypto)
+ get_target_property(_curl_imported OpenSSL::Crypto IMPORTED)
+ if(_curl_imported)
+ add_library(CURL::OpenSSL_Crypto INTERFACE IMPORTED)
+ get_target_property(_curl_libname OpenSSL::Crypto LOCATION)
+ set_target_properties(CURL::OpenSSL_Crypto PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
+ list(APPEND CURL_LIBS CURL::OpenSSL_Crypto)
endif()
- endforeach()
+ endif()
+ if(HAVE_LIBZ AND TARGET ZLIB::ZLIB)
+ get_target_property(_curl_imported ZLIB::ZLIB IMPORTED)
+ if(_curl_imported)
+ add_library(CURL::ZLIB INTERFACE IMPORTED)
+ get_target_property(_curl_libname ZLIB::ZLIB LOCATION)
+ set_target_properties(CURL::ZLIB PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
+ list(APPEND CURL_LIBS CURL::ZLIB)
+ endif()
+ endif()
if(WIN32)
add_library(CURL::win32_winsock INTERFACE IMPORTED)
set_target_properties(CURL::win32_winsock PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32")
@@ -2114,7 +2158,7 @@
macro(curl_add_if _label)
# Needs to be a macro to allow this indirection
if(${ARGN})
- set(_items ${_items} "${_label}")
+ list(APPEND _items "${_label}")
endif()
endmacro()
@@ -2163,6 +2207,7 @@
curl_add_if("RTSP" NOT CURL_DISABLE_RTSP)
curl_add_if("RTMP" USE_LIBRTMP)
curl_add_if("MQTT" NOT CURL_DISABLE_MQTT)
+curl_add_if("MQTTS" NOT CURL_DISABLE_MQTT AND _ssl_enabled)
curl_add_if("WS" NOT CURL_DISABLE_WEBSOCKETS)
curl_add_if("WSS" NOT CURL_DISABLE_WEBSOCKETS AND _ssl_enabled)
if(_items)
@@ -2200,23 +2245,21 @@
(_use_curl_ntlm_core OR USE_WINDOWS_SSPI))
curl_add_if("TLS-SRP" USE_TLS_SRP)
curl_add_if("HTTP2" USE_NGHTTP2)
-curl_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_OPENSSL_QUIC)
+curl_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
curl_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
curl_add_if("HTTPS-proxy" NOT CURL_DISABLE_PROXY AND _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS
OR USE_SCHANNEL OR USE_RUSTLS OR USE_MBEDTLS OR
(USE_WOLFSSL AND HAVE_WOLFSSL_BIO_NEW)))
curl_add_if("Unicode" ENABLE_UNICODE)
-curl_add_if("threadsafe" HAVE_ATOMIC OR
- (USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR
- (WIN32 AND HAVE_WIN32_WINNT GREATER_EQUAL 0x0600))
+curl_add_if("threadsafe" HAVE_ATOMIC OR (USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR WIN32)
curl_add_if("Debug" ENABLE_DEBUG)
-curl_add_if("TrackMemory" ENABLE_CURLDEBUG)
curl_add_if("ECH" _ssl_enabled AND HAVE_ECH)
curl_add_if("HTTPSRR" _ssl_enabled AND USE_HTTPSRR)
curl_add_if("PSL" USE_LIBPSL)
curl_add_if("CAcert" CURL_CA_EMBED_SET)
curl_add_if("SSLS-EXPORT" _ssl_enabled AND USE_SSLS_EXPORT)
curl_add_if("AppleSecTrust" USE_APPLE_SECTRUST AND _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS))
+curl_add_if("NativeCA" NOT USE_APPLE_SECTRUST AND _ssl_enabled AND CURL_CA_NATIVE)
if(_items)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
list(SORT _items CASE INSENSITIVE)
@@ -2354,7 +2397,13 @@
if(NOT _libname AND NOT _libs AND NOT _libdirs)
message(WARNING "Bad lib in library list: ${_lib}")
endif()
- get_target_property(_modules "${_lib}" INTERFACE_LIBCURL_PC_MODULES)
+ if(_lib STREQUAL OpenSSL::SSL)
+ set(_modules "openssl")
+ elseif(_lib STREQUAL ZLIB::ZLIB)
+ set(_modules "zlib")
+ else()
+ get_target_property(_modules "${_lib}" INTERFACE_LIBCURL_PC_MODULES)
+ endif()
if(_modules)
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "${_modules}")
endif()
@@ -2374,8 +2423,7 @@
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20)
cmake_path(SET _libdir NORMALIZE "${_libdir}")
endif()
- list(FIND _sys_libdirs "${_libdir}" _libdir_index)
- if(_libdir_index LESS 0)
+ if(NOT _libdir IN_LIST _sys_libdirs)
list(APPEND _ldflags "-L${_libdir}")
endif()
string(REGEX REPLACE "^lib" "" _libname "${_libname}")
@@ -2403,8 +2451,7 @@
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20)
cmake_path(SET _libdir NORMALIZE "${_libdir}")
endif()
- list(FIND _sys_libdirs "${_libdir}" _libdir_index)
- if(_libdir_index LESS 0)
+ if(NOT _libdir IN_LIST _sys_libdirs)
list(APPEND _ldflags "-L${_libdir}")
endif()
endforeach()
@@ -2509,8 +2556,7 @@
FILES_MATCHING PATTERN "*.h")
include(CMakePackageConfigHelpers)
- write_basic_package_version_file(
- "${_version_config}"
+ write_basic_package_version_file("${_version_config}"
VERSION ${_curl_version}
COMPATIBILITY SameMajorVersion)
file(READ "${_version_config}" _generated_version_config)
@@ -2532,6 +2578,7 @@
# TARGETS_EXPORT_NAME
# CURL_SUPPORTED_FEATURES_LIST
# CURL_SUPPORTED_PROTOCOLS_LIST
+ # CURL_USE_PKGCONFIG
# HAVE_BROTLI
# HAVE_GSSAPI
# HAVE_LIBIDN2
diff --git a/Utilities/cmcurl/COPYING b/Utilities/cmcurl/COPYING
index 3fa85eb..2f71d999 100644
--- a/Utilities/cmcurl/COPYING
+++ b/Utilities/cmcurl/COPYING
@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2025, Daniel Stenberg, <daniel@haxx.se>, and many
+Copyright (c) 1996 - 2026, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index c73b93d..10351cb 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -59,7 +59,7 @@
#define CURL_IGNORE_DEPRECATION(statements) statements
#endif
-#include "curlver.h" /* libcurl version defines */
+#include "curlver.h" /* libcurl version defines */
#include "system.h" /* determine things runtime */
#include <stdio.h>
@@ -142,7 +142,7 @@
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
typedef int curl_socket_t;
-#define CURL_SOCKET_BAD -1
+#define CURL_SOCKET_BAD (-1)
#endif
#define curl_socket_typedef
#endif /* curl_socket_typedef */
@@ -820,7 +820,7 @@
* CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
* CURLAUTH_BEARER - HTTP Bearer token authentication
* CURLAUTH_ONLY - Use together with a single other type to force no
- * authentication or just that single type
+ * authentication or that single type
* CURLAUTH_ANY - All fine types set
* CURLAUTH_ANYSAFE - All fine types except Basic
*/
@@ -842,10 +842,13 @@
#define CURLAUTH_BEARER (((unsigned long)1) << 6)
#define CURLAUTH_AWS_SIGV4 (((unsigned long)1) << 7)
#define CURLAUTH_ONLY (((unsigned long)1) << 31)
-#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
-#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC | CURLAUTH_DIGEST_IE))
+#define CURLAUTH_ANY ((~CURLAUTH_DIGEST_IE) & \
+ ((unsigned long)0xffffffff))
+#define CURLAUTH_ANYSAFE ((~(CURLAUTH_BASIC | CURLAUTH_DIGEST_IE)) & \
+ ((unsigned long)0xffffffff))
-#define CURLSSH_AUTH_ANY ~0L /* all types supported by server */
+/* all types supported by server */
+#define CURLSSH_AUTH_ANY ((unsigned long)0xffffffff)
#define CURLSSH_AUTH_NONE 0L /* none allowed, silly but complete */
#define CURLSSH_AUTH_PUBLICKEY (1L << 0) /* public/private key files */
#define CURLSSH_AUTH_PASSWORD (1L << 1) /* password */
@@ -1100,7 +1103,8 @@
#define CURLPROTO_SMBS (1L << 27)
#define CURLPROTO_MQTT (1L << 28)
#define CURLPROTO_GOPHERS (1L << 29)
-#define CURLPROTO_ALL (~0L) /* enable everything */
+#define CURLPROTO_ALL ((unsigned long)0xffffffff) /* old-style enable
+ "everything" */
/* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */
@@ -1113,8 +1117,9 @@
/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
string options from the header file */
-#define CURLOPT(na,t,nu) na = t + nu
-#define CURLOPTDEPRECATED(na,t,nu,v,m) na CURL_DEPRECATED(v,m) = t + nu
+#define CURLOPT(na, t, nu) na = ((t) + (nu))
+#define CURLOPTDEPRECATED(na, t, nu, v, m) na CURL_DEPRECATED(v, m) \
+ = ((t) + (nu))
/* CURLOPT aliases that make no runtime difference */
@@ -1244,7 +1249,7 @@
CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28),
/* send FILE * or void * to store headers to, if you use a callback it
- is simply passed to the callback unmodified */
+ is passed to the callback unmodified */
CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29),
/* point to a file to read the initial cookies from, also enables
@@ -1353,7 +1358,7 @@
/* Set the krb4/5 security level, this also enables krb4/5 awareness. This
* is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
- * is set but does not match one of these, 'private' will be used. */
+ * is set but does not match one of these, 'private' will be used. */
CURLOPTDEPRECATED(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63,
8.17.0, "removed"),
@@ -2119,7 +2124,7 @@
/* Specify URL using CURL URL API. */
CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282),
- /* add trailing data just after no more data is available */
+ /* add trailing data after no more data is available */
CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283),
/* pointer to be passed to HTTP_TRAILER_FUNCTION */
@@ -2198,7 +2203,7 @@
CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, CURLOPTTYPE_STRINGPOINT, 311),
/* Function that will be called immediately before the initial request
- is made on a connection (after any protocol negotiation step). */
+ is made on a connection (after any protocol negotiation step). */
CURLOPT(CURLOPT_PREREQFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 312),
/* Data passed to the CURLOPT_PREREQFUNCTION callback */
@@ -2278,7 +2283,6 @@
#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
-/* */
#define CURLOPT_FTP_RESPONSE_TIMEOUT CURLOPT_SERVER_RESPONSE_TIMEOUT
/* Added in 8.2.0 */
@@ -2352,8 +2356,8 @@
Unless one is set programmatically, the
.netrc will be queried. */
enum CURL_NETRC_OPTION {
- /* we set a single member here, just to make sure we still provide the enum,
- but the values to use are defined above with L suffixes */
+ /* we set a single member here, to make sure we still provide the enum, but
+ the values to use are defined above with L suffixes */
CURL_NETRC_LAST = 3
};
@@ -2382,7 +2386,7 @@
#define CURL_TLSAUTH_SRP 1L
enum CURL_TLSAUTH {
- /* we set a single member here, just to make sure we still provide the enum,
+ /* we set a single member here, to make sure we still provide the enum,
but the values to use are defined above with L suffixes */
CURL_TLSAUTH_LAST = 2
};
@@ -2405,7 +2409,7 @@
#define CURL_TIMECOND_LASTMOD 3L
typedef enum {
- /* we set a single member here, just to make sure we still provide
+ /* we set a single member here, to make sure we still provide
the enum typedef, but the values to use are defined above with L
suffixes */
CURL_TIMECOND_LAST = 4
@@ -2704,7 +2708,7 @@
*
* DESCRIPTION
*
- * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8-bit
* versions). This function returns a new allocated string or NULL if an error
* occurred.
* Conversion Note: On non-ASCII platforms the ASCII %XX codes are
@@ -3020,9 +3024,8 @@
/* Different data locks for a single share */
typedef enum {
CURL_LOCK_DATA_NONE = 0,
- /* CURL_LOCK_DATA_SHARE is used internally to say that
- * the locking is just made to change the internal state of the share
- * itself.
+ /* CURL_LOCK_DATA_SHARE is used internally to say that the locking is made
+ * to change the internal state of the share itself.
*/
CURL_LOCK_DATA_SHARE,
CURL_LOCK_DATA_COOKIE,
@@ -3096,11 +3099,10 @@
CURLVERSION_LAST /* never actually use this */
} CURLversion;
-/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
- basically all programs ever that want to get version information. It is
- meant to be a built-in version number for what kind of struct the caller
- expects. If the struct ever changes, we redefine the NOW to another enum
- from above. */
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by programs
+ that want to get version information. It is meant to be a built-in
+ version number for what kind of struct the caller expects. If the struct
+ ever changes, we redefine the NOW to another enum from above. */
#define CURLVERSION_NOW CURLVERSION_TWELFTH
struct curl_version_info_data {
@@ -3183,7 +3185,8 @@
supported */
#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */
#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */
-#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */
+#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported
+ (deprecated) */
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper
is supported */
@@ -3212,7 +3215,7 @@
* This function returns a pointer to a static copy of the version info
* struct. See above.
*/
-CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion stamp);
/*
* NAME curl_easy_strerror()
@@ -3223,7 +3226,7 @@
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
-CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+CURL_EXTERN const char *curl_easy_strerror(CURLcode error);
/*
* NAME curl_share_strerror()
@@ -3234,7 +3237,7 @@
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
-CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode error);
/*
* NAME curl_easy_pause()
@@ -3248,10 +3251,10 @@
CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#define CURLPAUSE_RECV (1 << 0)
-#define CURLPAUSE_RECV_CONT (0)
+#define CURLPAUSE_RECV_CONT 0
#define CURLPAUSE_SEND (1 << 2)
-#define CURLPAUSE_SEND_CONT (0)
+#define CURLPAUSE_SEND_CONT 0
#define CURLPAUSE_ALL (CURLPAUSE_RECV | CURLPAUSE_SEND)
#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT | CURLPAUSE_SEND_CONT)
@@ -3304,7 +3307,7 @@
#endif
/* unfortunately, the easy.h and multi.h include files need options and info
- stuff before they can be included! */
+ stuff before they can be included! */
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
#include "urlapi.h"
@@ -3324,11 +3327,16 @@
#if 0 /* Triggers clang -Wdisabled-macro-expansion, skip for CMake. */
/* This preprocessor magic that replaces a call with the exact same call is
only done to make sure application authors pass exactly three arguments
- to these functions. */
-#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
-#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
-#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
-#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+ to these functions. Use recursive macros to allow using these symbols via
+ the C++ global namespace '::' or reusing them as method names. */
+#define curl_easy_setopt(handle, opt, param) \
+ curl_easy_setopt(handle, opt, param)
+#define curl_easy_getinfo(handle, info, arg) \
+ curl_easy_getinfo(handle, info, arg)
+#define curl_share_setopt(share, opt, param) \
+ curl_share_setopt(share, opt, param)
+#define curl_multi_setopt(handle, opt, param) \
+ curl_multi_setopt(handle, opt, param)
#endif
#endif /* __STDC__ >= 1 */
#endif /* gcc >= 4.3 && !__cplusplus && !CURL_DISABLE_TYPECHECK */
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 999e312..2ea215b 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -32,12 +32,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "8.18.0"
+#define LIBCURL_VERSION "8.19.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 18
+#define LIBCURL_VERSION_MINOR 19
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -58,7 +58,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x081200
+#define LIBCURL_VERSION_NUM 0x081300
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index 5b3cdbd..0be6915 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/include/curl/easy.h
@@ -78,7 +78,7 @@
* DESCRIPTION
*
* Re-initializes a curl handle to the default values. This puts back the
- * handle to the same state as it was in when it was just created.
+ * handle to the same state as it was in when it was created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
diff --git a/Utilities/cmcurl/include/curl/header.h b/Utilities/cmcurl/include/curl/header.h
index e7334b5..85c10c8 100644
--- a/Utilities/cmcurl/include/curl/header.h
+++ b/Utilities/cmcurl/include/curl/header.h
@@ -31,7 +31,7 @@
struct curl_header {
char *name; /* this might not use the same case */
char *value;
- size_t amount; /* number of headers using this name */
+ size_t amount; /* number of headers using this name */
size_t index; /* ... of this instance, 0 or higher */
unsigned int origin; /* see bits below */
void *anchor; /* handle privately used by libcurl */
diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h
index 531c1a9..ad6f53f 100644
--- a/Utilities/cmcurl/include/curl/multi.h
+++ b/Utilities/cmcurl/include/curl/multi.h
@@ -77,9 +77,8 @@
CURLM_LAST
} CURLMcode;
-/* just to make code nicer when using curl_multi_socket() you can now check
- for CURLM_CALL_MULTI_SOCKET too in the same style it works for
- curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+/* You can check for CURLM_CALL_MULTI_SOCKET too in the same style it works
+ for curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
/* bitmask bits for CURLMOPT_PIPELINING */
@@ -201,13 +200,13 @@
/*
* Name: curl_multi_perform()
*
- * Desc: When the app thinks there is data available for curl it calls this
+ * Desc: When the app thinks there is data available for curl it calls this
* function to read/write whatever there is right now. This returns
* as soon as the reads and writes are done. This function does not
* require that there actually is data available for reading or that
- * data can be written, it can be called just in case. It returns
- * the number of handles that still transfer data in the second
- * argument's integer-pointer.
+ * data can be written, it can be called. It returns the number of
+ * handles that still transfer data in the second argument's
+ * integer-pointer.
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
@@ -234,7 +233,7 @@
*
* Desc: Ask the multi handle if there is any messages/informationals from
* the individual transfers. Messages include informationals such as
- * error code from the transfer or just the fact that a transfer is
+ * error code from the transfer or the fact that a transfer is
* completed. More details on these should be written down as well.
*
* Repeated calls to this function will return a new struct each
@@ -269,7 +268,7 @@
*
* Returns: A pointer to a null-terminated error message.
*/
-CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode error);
/*
* Name: curl_multi_socket() and
@@ -329,7 +328,7 @@
/* This macro below was added in 7.16.3 to push users who recompile to use
* the new curl_multi_socket_action() instead of the old curl_multi_socket()
*/
-#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
+#define curl_multi_socket(x, y, z) curl_multi_socket_action(x, y, 0, z)
#endif
/*
@@ -515,7 +514,7 @@
*
* Desc: Ask curl for fds for polling. The app can use these to poll on.
* We want curl_multi_perform() called as soon as one of them are
- * ready. Passing zero size allows to get just a number of fds.
+ * ready. Passing zero size allows to get a number of fds.
*
* Returns: CURLMcode type, general multi error code.
*/
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index a5b3e9e..064833d 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -367,20 +367,20 @@
#define CURL_PULL_SYS_POLL_H
#endif
-/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
-/* sys/types.h is required here to properly make type definitions below. */
+/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file
+ sys/types.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_TYPES_H
# include <sys/types.h>
#endif
-/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
-/* sys/socket.h is required here to properly make type definitions below. */
+/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file
+ sys/socket.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_SOCKET_H
# include <sys/socket.h>
#endif
-/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
-/* sys/poll.h is required here to properly make type definitions below. */
+/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file
+ sys/poll.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_POLL_H
# include <sys/poll.h>
#endif
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 0642afd..d9a672e 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -38,191 +38,191 @@
* when compiling with -Wlogical-op.
*
* To add an option that uses the same type as an existing option, you will
- * just need to extend the appropriate _curl_*_option macro
+ * need to extend the appropriate _curl_*_option macro
*/
#define curl_easy_setopt(handle, option, value) \
__extension__({ \
- if(__builtin_constant_p(option)) { \
- CURL_IGNORE_DEPRECATION( \
- if(curlcheck_long_option(option)) \
- if(!curlcheck_long(value)) \
- Wcurl_easy_setopt_err_long(); \
- if(curlcheck_off_t_option(option)) \
- if(!curlcheck_off_t(value)) \
- Wcurl_easy_setopt_err_curl_off_t(); \
- if(curlcheck_string_option(option)) \
- if(!curlcheck_string(value)) \
- Wcurl_easy_setopt_err_string(); \
- if((option) == CURLOPT_PRIVATE) { } \
- if(curlcheck_write_cb_option(option)) \
- if(!curlcheck_write_cb(value)) \
- Wcurl_easy_setopt_err_write_callback(); \
- if(curlcheck_curl_option(option)) \
- if(!curlcheck_curl(value)) \
- Wcurl_easy_setopt_err_curl(); \
- if((option) == CURLOPT_RESOLVER_START_FUNCTION) \
- if(!curlcheck_resolver_start_callback(value)) \
- Wcurl_easy_setopt_err_resolver_start_callback(); \
- if((option) == CURLOPT_READFUNCTION) \
- if(!curlcheck_read_cb(value)) \
- Wcurl_easy_setopt_err_read_cb(); \
- if((option) == CURLOPT_IOCTLFUNCTION) \
- if(!curlcheck_ioctl_cb(value)) \
- Wcurl_easy_setopt_err_ioctl_cb(); \
- if((option) == CURLOPT_SOCKOPTFUNCTION) \
- if(!curlcheck_sockopt_cb(value)) \
- Wcurl_easy_setopt_err_sockopt_cb(); \
- if((option) == CURLOPT_OPENSOCKETFUNCTION) \
- if(!curlcheck_opensocket_cb(value)) \
- Wcurl_easy_setopt_err_opensocket_cb(); \
- if((option) == CURLOPT_PROGRESSFUNCTION) \
- if(!curlcheck_progress_cb(value)) \
- Wcurl_easy_setopt_err_progress_cb(); \
- if((option) == CURLOPT_XFERINFOFUNCTION) \
- if(!curlcheck_xferinfo_cb(value)) \
- Wcurl_easy_setopt_err_xferinfo_cb(); \
- if((option) == CURLOPT_DEBUGFUNCTION) \
- if(!curlcheck_debug_cb(value)) \
- Wcurl_easy_setopt_err_debug_cb(); \
- if((option) == CURLOPT_SSL_CTX_FUNCTION) \
- if(!curlcheck_ssl_ctx_cb(value)) \
- Wcurl_easy_setopt_err_ssl_ctx_cb(); \
- if(curlcheck_conv_cb_option(option)) \
- if(!curlcheck_conv_cb(value)) \
- Wcurl_easy_setopt_err_conv_cb(); \
- if((option) == CURLOPT_SEEKFUNCTION) \
- if(!curlcheck_seek_cb(value)) \
- Wcurl_easy_setopt_err_seek_cb(); \
- if((option) == CURLOPT_CHUNK_BGN_FUNCTION) \
- if(!curlcheck_chunk_bgn_cb(value)) \
- Wcurl_easy_setopt_err_chunk_bgn_cb(); \
- if((option) == CURLOPT_CHUNK_END_FUNCTION) \
- if(!curlcheck_chunk_end_cb(value)) \
- Wcurl_easy_setopt_err_chunk_end_cb(); \
- if((option) == CURLOPT_CLOSESOCKETFUNCTION) \
- if(!curlcheck_close_socket_cb(value)) \
- Wcurl_easy_setopt_err_close_socket_cb(); \
- if((option) == CURLOPT_FNMATCH_FUNCTION) \
- if(!curlcheck_fnmatch_cb(value)) \
- Wcurl_easy_setopt_err_fnmatch_cb(); \
- if((option) == CURLOPT_HSTSREADFUNCTION) \
- if(!curlcheck_hstsread_cb(value)) \
- Wcurl_easy_setopt_err_hstsread_cb(); \
- if((option) == CURLOPT_HSTSWRITEFUNCTION) \
- if(!curlcheck_hstswrite_cb(value)) \
- Wcurl_easy_setopt_err_hstswrite_cb(); \
- if((option) == CURLOPT_SSH_HOSTKEYFUNCTION) \
- if(!curlcheck_ssh_hostkey_cb(value)) \
- Wcurl_easy_setopt_err_ssh_hostkey_cb(); \
- if((option) == CURLOPT_SSH_KEYFUNCTION) \
- if(!curlcheck_ssh_key_cb(value)) \
- Wcurl_easy_setopt_err_ssh_key_cb(); \
- if((option) == CURLOPT_INTERLEAVEFUNCTION) \
- if(!curlcheck_interleave_cb(value)) \
- Wcurl_easy_setopt_err_interleave_cb(); \
- if((option) == CURLOPT_PREREQFUNCTION) \
- if(!curlcheck_prereq_cb(value)) \
- Wcurl_easy_setopt_err_prereq_cb(); \
- if((option) == CURLOPT_TRAILERFUNCTION) \
- if(!curlcheck_trailer_cb(value)) \
- Wcurl_easy_setopt_err_trailer_cb(); \
- if(curlcheck_cb_data_option(option)) \
- if(!curlcheck_cb_data(value)) \
- Wcurl_easy_setopt_err_cb_data(); \
- if((option) == CURLOPT_ERRORBUFFER) \
- if(!curlcheck_error_buffer(value)) \
- Wcurl_easy_setopt_err_error_buffer(); \
- if((option) == CURLOPT_CURLU) \
- if(!curlcheck_ptr((value), CURLU)) \
- Wcurl_easy_setopt_err_curlu(); \
- if((option) == CURLOPT_STDERR) \
- if(!curlcheck_FILE(value)) \
- Wcurl_easy_setopt_err_FILE(); \
- if(curlcheck_postfields_option(option)) \
- if(!curlcheck_postfields(value)) \
- Wcurl_easy_setopt_err_postfields(); \
- if((option) == CURLOPT_HTTPPOST) \
- if(!curlcheck_arr((value), struct curl_httppost)) \
- Wcurl_easy_setopt_err_curl_httpost(); \
- if((option) == CURLOPT_MIMEPOST) \
- if(!curlcheck_ptr((value), curl_mime)) \
- Wcurl_easy_setopt_err_curl_mimepost(); \
- if(curlcheck_slist_option(option)) \
- if(!curlcheck_arr((value), struct curl_slist)) \
- Wcurl_easy_setopt_err_curl_slist(); \
- if((option) == CURLOPT_SHARE) \
- if(!curlcheck_ptr((value), CURLSH)) \
- Wcurl_easy_setopt_err_CURLSH(); \
- ) \
- } \
- curl_easy_setopt(handle, option, value); \
- })
+ if(__builtin_constant_p(option)) { \
+ CURL_IGNORE_DEPRECATION( \
+ if(curlcheck_long_option(option)) \
+ if(!curlcheck_long(value)) \
+ Wcurl_easy_setopt_err_long(); \
+ if(curlcheck_off_t_option(option)) \
+ if(!curlcheck_off_t(value)) \
+ Wcurl_easy_setopt_err_curl_off_t(); \
+ if(curlcheck_string_option(option)) \
+ if(!curlcheck_string(value)) \
+ Wcurl_easy_setopt_err_string(); \
+ if((option) == CURLOPT_PRIVATE) { } \
+ if(curlcheck_write_cb_option(option)) \
+ if(!curlcheck_write_cb(value)) \
+ Wcurl_easy_setopt_err_write_callback(); \
+ if(curlcheck_curl_option(option)) \
+ if(!curlcheck_curl(value)) \
+ Wcurl_easy_setopt_err_curl(); \
+ if((option) == CURLOPT_RESOLVER_START_FUNCTION) \
+ if(!curlcheck_resolver_start_callback(value)) \
+ Wcurl_easy_setopt_err_resolver_start_callback(); \
+ if((option) == CURLOPT_READFUNCTION) \
+ if(!curlcheck_read_cb(value)) \
+ Wcurl_easy_setopt_err_read_cb(); \
+ if((option) == CURLOPT_IOCTLFUNCTION) \
+ if(!curlcheck_ioctl_cb(value)) \
+ Wcurl_easy_setopt_err_ioctl_cb(); \
+ if((option) == CURLOPT_SOCKOPTFUNCTION) \
+ if(!curlcheck_sockopt_cb(value)) \
+ Wcurl_easy_setopt_err_sockopt_cb(); \
+ if((option) == CURLOPT_OPENSOCKETFUNCTION) \
+ if(!curlcheck_opensocket_cb(value)) \
+ Wcurl_easy_setopt_err_opensocket_cb(); \
+ if((option) == CURLOPT_PROGRESSFUNCTION) \
+ if(!curlcheck_progress_cb(value)) \
+ Wcurl_easy_setopt_err_progress_cb(); \
+ if((option) == CURLOPT_XFERINFOFUNCTION) \
+ if(!curlcheck_xferinfo_cb(value)) \
+ Wcurl_easy_setopt_err_xferinfo_cb(); \
+ if((option) == CURLOPT_DEBUGFUNCTION) \
+ if(!curlcheck_debug_cb(value)) \
+ Wcurl_easy_setopt_err_debug_cb(); \
+ if((option) == CURLOPT_SSL_CTX_FUNCTION) \
+ if(!curlcheck_ssl_ctx_cb(value)) \
+ Wcurl_easy_setopt_err_ssl_ctx_cb(); \
+ if(curlcheck_conv_cb_option(option)) \
+ if(!curlcheck_conv_cb(value)) \
+ Wcurl_easy_setopt_err_conv_cb(); \
+ if((option) == CURLOPT_SEEKFUNCTION) \
+ if(!curlcheck_seek_cb(value)) \
+ Wcurl_easy_setopt_err_seek_cb(); \
+ if((option) == CURLOPT_CHUNK_BGN_FUNCTION) \
+ if(!curlcheck_chunk_bgn_cb(value)) \
+ Wcurl_easy_setopt_err_chunk_bgn_cb(); \
+ if((option) == CURLOPT_CHUNK_END_FUNCTION) \
+ if(!curlcheck_chunk_end_cb(value)) \
+ Wcurl_easy_setopt_err_chunk_end_cb(); \
+ if((option) == CURLOPT_CLOSESOCKETFUNCTION) \
+ if(!curlcheck_close_socket_cb(value)) \
+ Wcurl_easy_setopt_err_close_socket_cb(); \
+ if((option) == CURLOPT_FNMATCH_FUNCTION) \
+ if(!curlcheck_fnmatch_cb(value)) \
+ Wcurl_easy_setopt_err_fnmatch_cb(); \
+ if((option) == CURLOPT_HSTSREADFUNCTION) \
+ if(!curlcheck_hstsread_cb(value)) \
+ Wcurl_easy_setopt_err_hstsread_cb(); \
+ if((option) == CURLOPT_HSTSWRITEFUNCTION) \
+ if(!curlcheck_hstswrite_cb(value)) \
+ Wcurl_easy_setopt_err_hstswrite_cb(); \
+ if((option) == CURLOPT_SSH_HOSTKEYFUNCTION) \
+ if(!curlcheck_ssh_hostkey_cb(value)) \
+ Wcurl_easy_setopt_err_ssh_hostkey_cb(); \
+ if((option) == CURLOPT_SSH_KEYFUNCTION) \
+ if(!curlcheck_ssh_key_cb(value)) \
+ Wcurl_easy_setopt_err_ssh_key_cb(); \
+ if((option) == CURLOPT_INTERLEAVEFUNCTION) \
+ if(!curlcheck_interleave_cb(value)) \
+ Wcurl_easy_setopt_err_interleave_cb(); \
+ if((option) == CURLOPT_PREREQFUNCTION) \
+ if(!curlcheck_prereq_cb(value)) \
+ Wcurl_easy_setopt_err_prereq_cb(); \
+ if((option) == CURLOPT_TRAILERFUNCTION) \
+ if(!curlcheck_trailer_cb(value)) \
+ Wcurl_easy_setopt_err_trailer_cb(); \
+ if(curlcheck_cb_data_option(option)) \
+ if(!curlcheck_cb_data(value)) \
+ Wcurl_easy_setopt_err_cb_data(); \
+ if((option) == CURLOPT_ERRORBUFFER) \
+ if(!curlcheck_error_buffer(value)) \
+ Wcurl_easy_setopt_err_error_buffer(); \
+ if((option) == CURLOPT_CURLU) \
+ if(!curlcheck_ptr((value), CURLU)) \
+ Wcurl_easy_setopt_err_curlu(); \
+ if((option) == CURLOPT_STDERR) \
+ if(!curlcheck_FILE(value)) \
+ Wcurl_easy_setopt_err_FILE(); \
+ if(curlcheck_postfields_option(option)) \
+ if(!curlcheck_postfields(value)) \
+ Wcurl_easy_setopt_err_postfields(); \
+ if((option) == CURLOPT_HTTPPOST) \
+ if(!curlcheck_arr((value), struct curl_httppost)) \
+ Wcurl_easy_setopt_err_curl_httpost(); \
+ if((option) == CURLOPT_MIMEPOST) \
+ if(!curlcheck_ptr((value), curl_mime)) \
+ Wcurl_easy_setopt_err_curl_mimepost(); \
+ if(curlcheck_slist_option(option)) \
+ if(!curlcheck_arr((value), struct curl_slist)) \
+ Wcurl_easy_setopt_err_curl_slist(); \
+ if((option) == CURLOPT_SHARE) \
+ if(!curlcheck_ptr((value), CURLSH)) \
+ Wcurl_easy_setopt_err_CURLSH(); \
+ ) \
+ } \
+ (curl_easy_setopt)(handle, option, value); \
+ })
/* wraps curl_easy_getinfo() with type checking */
#define curl_easy_getinfo(handle, info, arg) \
__extension__({ \
- if(__builtin_constant_p(info)) { \
- CURL_IGNORE_DEPRECATION( \
- if(curlcheck_string_info(info)) \
- if(!curlcheck_arr((arg), char *)) \
- Wcurl_easy_getinfo_err_string(); \
- if(curlcheck_long_info(info)) \
- if(!curlcheck_arr((arg), long)) \
- Wcurl_easy_getinfo_err_long(); \
- if(curlcheck_double_info(info)) \
- if(!curlcheck_arr((arg), double)) \
- Wcurl_easy_getinfo_err_double(); \
- if(curlcheck_slist_info(info)) \
- if(!curlcheck_arr((arg), struct curl_slist *)) \
- Wcurl_easy_getinfo_err_curl_slist(); \
- if(curlcheck_tlssessioninfo_info(info)) \
- if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
- Wcurl_easy_getinfo_err_curl_tlssessioninfo(); \
- if(curlcheck_certinfo_info(info)) \
- if(!curlcheck_arr((arg), struct curl_certinfo *)) \
- Wcurl_easy_getinfo_err_curl_certinfo(); \
- if(curlcheck_socket_info(info)) \
- if(!curlcheck_arr((arg), curl_socket_t)) \
- Wcurl_easy_getinfo_err_curl_socket(); \
- if(curlcheck_off_t_info(info)) \
- if(!curlcheck_arr((arg), curl_off_t)) \
- Wcurl_easy_getinfo_err_curl_off_t(); \
- ) \
- } \
- curl_easy_getinfo(handle, info, arg); \
- })
+ if(__builtin_constant_p(info)) { \
+ CURL_IGNORE_DEPRECATION( \
+ if(curlcheck_string_info(info)) \
+ if(!curlcheck_arr((arg), char *)) \
+ Wcurl_easy_getinfo_err_string(); \
+ if(curlcheck_long_info(info)) \
+ if(!curlcheck_arr((arg), long)) \
+ Wcurl_easy_getinfo_err_long(); \
+ if(curlcheck_double_info(info)) \
+ if(!curlcheck_arr((arg), double)) \
+ Wcurl_easy_getinfo_err_double(); \
+ if(curlcheck_slist_info(info)) \
+ if(!curlcheck_arr((arg), struct curl_slist *)) \
+ Wcurl_easy_getinfo_err_curl_slist(); \
+ if(curlcheck_tlssessioninfo_info(info)) \
+ if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
+ Wcurl_easy_getinfo_err_curl_tlssessioninfo(); \
+ if(curlcheck_certinfo_info(info)) \
+ if(!curlcheck_arr((arg), struct curl_certinfo *)) \
+ Wcurl_easy_getinfo_err_curl_certinfo(); \
+ if(curlcheck_socket_info(info)) \
+ if(!curlcheck_arr((arg), curl_socket_t)) \
+ Wcurl_easy_getinfo_err_curl_socket(); \
+ if(curlcheck_off_t_info(info)) \
+ if(!curlcheck_arr((arg), curl_off_t)) \
+ Wcurl_easy_getinfo_err_curl_off_t(); \
+ ) \
+ } \
+ (curl_easy_getinfo)(handle, info, arg); \
+ })
#define curl_multi_setopt(handle, option, value) \
__extension__({ \
- if(__builtin_constant_p(option)) { \
- if(curlcheck_long_option(option)) \
- if(!curlcheck_long(value)) \
- Wcurl_multi_setopt_err_long(); \
- if(curlcheck_off_t_option(option)) \
- if(!curlcheck_off_t(value)) \
- Wcurl_multi_setopt_err_curl_off_t(); \
- if(curlcheck_multicb_data_option(option)) \
- if(!curlcheck_cb_data(value)) \
- Wcurl_multi_setopt_err_cb_data(); \
- if(curlcheck_charpp_option(option)) \
- if(!curlcheck_ptrptr(value, char)) \
- Wcurl_multi_setopt_err_charpp(); \
- if((option) == CURLMOPT_NOTIFYFUNCTION) \
- if(!curlcheck_multinotify_cb(value)) \
- Wcurl_multi_setopt_err_notifycb(); \
- if((option) == CURLMOPT_PUSHFUNCTION) \
- if(!curlcheck_multipush_cb(value)) \
- Wcurl_multi_setopt_err_pushcb(); \
- if((option) == CURLMOPT_SOCKETFUNCTION) \
- if(!curlcheck_multisocket_cb(value)) \
- Wcurl_multi_setopt_err_socketcb(); \
- if((option) == CURLMOPT_TIMERFUNCTION) \
- if(!curlcheck_multitimer_cb(value)) \
- Wcurl_multi_setopt_err_timercb(); \
- } \
- curl_multi_setopt(handle, option, value); \
- })
+ if(__builtin_constant_p(option)) { \
+ if(curlcheck_long_option(option)) \
+ if(!curlcheck_long(value)) \
+ Wcurl_multi_setopt_err_long(); \
+ if(curlcheck_off_t_option(option)) \
+ if(!curlcheck_off_t(value)) \
+ Wcurl_multi_setopt_err_curl_off_t(); \
+ if(curlcheck_multicb_data_option(option)) \
+ if(!curlcheck_cb_data(value)) \
+ Wcurl_multi_setopt_err_cb_data(); \
+ if(curlcheck_charpp_option(option)) \
+ if(!curlcheck_ptrptr(value, char)) \
+ Wcurl_multi_setopt_err_charpp(); \
+ if((option) == CURLMOPT_NOTIFYFUNCTION) \
+ if(!curlcheck_multinotify_cb(value)) \
+ Wcurl_multi_setopt_err_notifycb(); \
+ if((option) == CURLMOPT_PUSHFUNCTION) \
+ if(!curlcheck_multipush_cb(value)) \
+ Wcurl_multi_setopt_err_pushcb(); \
+ if((option) == CURLMOPT_SOCKETFUNCTION) \
+ if(!curlcheck_multisocket_cb(value)) \
+ Wcurl_multi_setopt_err_socketcb(); \
+ if((option) == CURLMOPT_TIMERFUNCTION) \
+ if(!curlcheck_multitimer_cb(value)) \
+ Wcurl_multi_setopt_err_timercb(); \
+ } \
+ (curl_multi_setopt)(handle, option, value); \
+ })
/* evaluates to true if the option takes a data argument to pass to a
callback */
@@ -260,9 +260,10 @@
curlcheck_cb_compatible((expr), curl_notify_callback))
/*
- * For now, just make sure that the functions are called with three arguments
+ * Make sure that the functions are called with three arguments
*/
-#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_share_setopt(share, opt, param) \
+ (curl_share_setopt)(share, opt, param)
/* the actual warnings, triggered by calling the Wcurl_easy_setopt_err*
* functions */
@@ -511,82 +512,84 @@
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
/* evaluates to true if option takes a data argument to pass to a callback */
-#define curlcheck_cb_data_option(option) \
- ((option) == CURLOPT_CHUNK_DATA || \
- (option) == CURLOPT_CLOSESOCKETDATA || \
- (option) == CURLOPT_DEBUGDATA || \
- (option) == CURLOPT_FNMATCH_DATA || \
- (option) == CURLOPT_HEADERDATA || \
- (option) == CURLOPT_HSTSREADDATA || \
- (option) == CURLOPT_HSTSWRITEDATA || \
- (option) == CURLOPT_INTERLEAVEDATA || \
- (option) == CURLOPT_IOCTLDATA || \
- (option) == CURLOPT_OPENSOCKETDATA || \
- (option) == CURLOPT_PREREQDATA || \
- (option) == CURLOPT_XFERINFODATA || \
- (option) == CURLOPT_READDATA || \
- (option) == CURLOPT_SEEKDATA || \
- (option) == CURLOPT_SOCKOPTDATA || \
- (option) == CURLOPT_SSH_KEYDATA || \
- (option) == CURLOPT_SSL_CTX_DATA || \
- (option) == CURLOPT_WRITEDATA || \
- (option) == CURLOPT_RESOLVER_START_DATA || \
- (option) == CURLOPT_TRAILERDATA || \
- (option) == CURLOPT_SSH_HOSTKEYDATA || \
+#define curlcheck_cb_data_option(option) \
+ ((option) == CURLOPT_CHUNK_DATA || \
+ (option) == CURLOPT_CLOSESOCKETDATA || \
+ (option) == CURLOPT_DEBUGDATA || \
+ (option) == CURLOPT_FNMATCH_DATA || \
+ (option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_HSTSREADDATA || \
+ (option) == CURLOPT_HSTSWRITEDATA || \
+ (option) == CURLOPT_INTERLEAVEDATA || \
+ (option) == CURLOPT_IOCTLDATA || \
+ (option) == CURLOPT_OPENSOCKETDATA || \
+ (option) == CURLOPT_PREREQDATA || \
+ (option) == CURLOPT_XFERINFODATA || \
+ (option) == CURLOPT_READDATA || \
+ (option) == CURLOPT_SEEKDATA || \
+ (option) == CURLOPT_SOCKOPTDATA || \
+ (option) == CURLOPT_SSH_KEYDATA || \
+ (option) == CURLOPT_SSL_CTX_DATA || \
+ (option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_RESOLVER_START_DATA || \
+ (option) == CURLOPT_TRAILERDATA || \
+ (option) == CURLOPT_SSH_HOSTKEYDATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
-#define curlcheck_postfields_option(option) \
- ((option) == CURLOPT_POSTFIELDS || \
- (option) == CURLOPT_COPYPOSTFIELDS || \
+#define curlcheck_postfields_option(option) \
+ ((option) == CURLOPT_POSTFIELDS || \
+ (option) == CURLOPT_COPYPOSTFIELDS || \
0)
/* evaluates to true if option takes a struct curl_slist * argument */
-#define curlcheck_slist_option(option) \
- ((option) == CURLOPT_HTTP200ALIASES || \
- (option) == CURLOPT_HTTPHEADER || \
- (option) == CURLOPT_MAIL_RCPT || \
- (option) == CURLOPT_POSTQUOTE || \
- (option) == CURLOPT_PREQUOTE || \
- (option) == CURLOPT_PROXYHEADER || \
- (option) == CURLOPT_QUOTE || \
- (option) == CURLOPT_RESOLVE || \
- (option) == CURLOPT_TELNETOPTIONS || \
- (option) == CURLOPT_CONNECT_TO || \
+#define curlcheck_slist_option(option) \
+ ((option) == CURLOPT_HTTP200ALIASES || \
+ (option) == CURLOPT_HTTPHEADER || \
+ (option) == CURLOPT_MAIL_RCPT || \
+ (option) == CURLOPT_POSTQUOTE || \
+ (option) == CURLOPT_PREQUOTE || \
+ (option) == CURLOPT_PROXYHEADER || \
+ (option) == CURLOPT_QUOTE || \
+ (option) == CURLOPT_RESOLVE || \
+ (option) == CURLOPT_TELNETOPTIONS || \
+ (option) == CURLOPT_CONNECT_TO || \
0)
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
-#define curlcheck_string_info(info) \
- (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
+#define curlcheck_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
(info) != CURLINFO_PRIVATE)
/* evaluates to true if info expects a pointer to long argument */
-#define curlcheck_long_info(info) \
+#define curlcheck_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
-#define curlcheck_double_info(info) \
+#define curlcheck_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
#define curlcheck_slist_info(info) \
- (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
+ (((info) == CURLINFO_SSL_ENGINES) || \
+ ((info) == CURLINFO_COOKIELIST))
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
-#define curlcheck_tlssessioninfo_info(info) \
- (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
+#define curlcheck_tlssessioninfo_info(info) \
+ (((info) == CURLINFO_TLS_SSL_PTR) || \
+ ((info) == CURLINFO_TLS_SESSION))
/* true if info expects a pointer to struct curl_certinfo * argument */
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
/* true if info expects a pointer to struct curl_socket_t argument */
-#define curlcheck_socket_info(info) \
+#define curlcheck_socket_info(info) \
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
/* true if info expects a pointer to curl_off_t argument */
-#define curlcheck_off_t_info(info) \
+#define curlcheck_off_t_info(info) \
(CURLINFO_OFF_T < (info))
/*
@@ -603,7 +606,7 @@
*/
/* XXX: should evaluate to true if expr is a pointer */
-#define curlcheck_any_ptr(expr) \
+#define curlcheck_any_ptr(expr) \
(sizeof(expr) == sizeof(void *))
/* evaluates to true if expr is NULL */
@@ -667,7 +670,7 @@
)
/* evaluates to true if expr is of type curl_off_t */
-#define curlcheck_off_t(expr) \
+#define curlcheck_off_t(expr) \
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
@@ -705,8 +708,8 @@
__builtin_types_compatible_p(__typeof__(func) *, type))
/* evaluates to true if expr is of type curl_resolver_start_callback */
-#define curlcheck_resolver_start_callback(expr) \
- (curlcheck_NULL(expr) || \
+#define curlcheck_resolver_start_callback(expr) \
+ (curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
@@ -740,11 +743,11 @@
curlcheck_cb_compatible((expr), Wcurl_write_callback6))
typedef size_t (*Wcurl_write_callback1)(const char *, size_t, size_t, void *);
typedef size_t (*Wcurl_write_callback2)(const char *, size_t, size_t,
- const void *);
+ const void *);
typedef size_t (*Wcurl_write_callback3)(const char *, size_t, size_t, FILE *);
typedef size_t (*Wcurl_write_callback4)(const void *, size_t, size_t, void *);
typedef size_t (*Wcurl_write_callback5)(const void *, size_t, size_t,
- const void *);
+ const void *);
typedef size_t (*Wcurl_write_callback6)(const void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
@@ -768,7 +771,7 @@
curlcheck_cb_compatible((expr), Wcurl_sockopt_callback2))
typedef int (*Wcurl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
typedef int (*Wcurl_sockopt_callback2)(const void *, curl_socket_t,
- curlsocktype);
+ curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or
"similar" */
@@ -816,21 +819,21 @@
curlcheck_cb_compatible((expr), Wcurl_debug_callback6) || \
curlcheck_cb_compatible((expr), Wcurl_debug_callback7) || \
curlcheck_cb_compatible((expr), Wcurl_debug_callback8))
-typedef int (*Wcurl_debug_callback1) (CURL *,
+typedef int (*Wcurl_debug_callback1)(CURL *,
curl_infotype, char *, size_t, void *);
-typedef int (*Wcurl_debug_callback2) (CURL *,
+typedef int (*Wcurl_debug_callback2)(CURL *,
curl_infotype, char *, size_t, const void *);
-typedef int (*Wcurl_debug_callback3) (CURL *,
+typedef int (*Wcurl_debug_callback3)(CURL *,
curl_infotype, const char *, size_t, void *);
-typedef int (*Wcurl_debug_callback4) (CURL *,
+typedef int (*Wcurl_debug_callback4)(CURL *,
curl_infotype, const char *, size_t, const void *);
-typedef int (*Wcurl_debug_callback5) (CURL *,
+typedef int (*Wcurl_debug_callback5)(CURL *,
curl_infotype, unsigned char *, size_t, void *);
-typedef int (*Wcurl_debug_callback6) (CURL *,
+typedef int (*Wcurl_debug_callback6)(CURL *,
curl_infotype, unsigned char *, size_t, const void *);
-typedef int (*Wcurl_debug_callback7) (CURL *,
+typedef int (*Wcurl_debug_callback7)(CURL *,
curl_infotype, const unsigned char *, size_t, void *);
-typedef int (*Wcurl_debug_callback8) (CURL *,
+typedef int (*Wcurl_debug_callback8)(CURL *,
curl_infotype, const unsigned char *, size_t, const void *);
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
diff --git a/Utilities/cmcurl/include/curl/urlapi.h b/Utilities/cmcurl/include/curl/urlapi.h
index dabe44a..f7a42b3 100644
--- a/Utilities/cmcurl/include/curl/urlapi.h
+++ b/Utilities/cmcurl/include/curl/urlapi.h
@@ -146,7 +146,7 @@
* readable error string. This is useful for printing meaningful error
* messages.
*/
-CURL_EXTERN const char *curl_url_strerror(CURLUcode);
+CURL_EXTERN const char *curl_url_strerror(CURLUcode error);
#ifdef __cplusplus
} /* end of extern "C" */
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index 5eef8df..673e9be 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -38,6 +38,7 @@
set_property(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
"${PROJECT_BINARY_DIR}/lib" # for "curl_config.h"
+ "${PROJECT_SOURCE_DIR}/lib"
)
#-----------------------------------------------------------------------------
@@ -80,13 +81,13 @@
#-----------------------------------------------------------------------------
if(CURL_BUILD_TESTING)
- # special libcurlu library just for unittests
+ # special libcurlu library for unittests
add_library(curlu STATIC EXCLUDE_FROM_ALL ${HHEADERS} ${CSOURCES})
target_compile_definitions(curlu PUBLIC "CURL_STATICLIB" "UNITTESTS")
target_link_libraries(curlu PUBLIC ${CURL_LIBS})
# There is plenty of parallelism when building the testdeps target.
# Override the curlu batch size with the maximum to optimize performance.
- set_target_properties(curlu PROPERTIES UNITY_BUILD_BATCH_SIZE 0 C_CLANG_TIDY "")
+ set_target_properties(curlu PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 0 C_CLANG_TIDY "")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/unitprotos.h"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
@@ -150,6 +151,7 @@
target_link_libraries(${LIB_OBJECT} PRIVATE ${CURL_LIBS})
set_target_properties(${LIB_OBJECT} PROPERTIES
POSITION_INDEPENDENT_CODE ON)
+ set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAGS}")
if(CURL_HIDES_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAG_SYMBOLS_HIDE}")
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
@@ -163,6 +165,9 @@
set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
+ if(CURL_CLANG_TIDY)
+ set_target_properties(${LIB_OBJECT} PROPERTIES UNITY_BUILD OFF)
+ endif()
if(CURL_CODE_COVERAGE)
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_COVERAGE_MACROS})
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_OPTIONS ${CURL_COVERAGE_CFLAGS})
@@ -191,6 +196,7 @@
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
+ set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAGS}")
if(CURL_HIDES_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAG_SYMBOLS_HIDE}")
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
@@ -204,6 +210,13 @@
set_target_properties(${LIB_STATIC} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
+ if(CURL_CLANG_TIDY)
+ if(BUILD_SHARED_LIBS) # disable clang-tidy for static, and limit to the shared library, if both enabled
+ set_target_properties(${LIB_STATIC} PROPERTIES C_CLANG_TIDY "")
+ else()
+ set_target_properties(${LIB_STATIC} PROPERTIES UNITY_BUILD OFF)
+ endif()
+ endif()
if(CURL_CODE_COVERAGE)
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_COVERAGE_MACROS})
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS ${CURL_COVERAGE_CFLAGS})
@@ -252,6 +265,7 @@
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
POSITION_INDEPENDENT_CODE ON)
+ set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAGS}")
if(CURL_HIDES_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAG_SYMBOLS_HIDE}")
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
@@ -265,6 +279,9 @@
set_target_properties(${LIB_SHARED} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
+ if(CURL_CLANG_TIDY)
+ set_target_properties(${LIB_SHARED} PROPERTIES UNITY_BUILD OFF)
+ endif()
if(CURL_CODE_COVERAGE)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_COVERAGE_MACROS})
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_OPTIONS ${CURL_COVERAGE_CFLAGS})
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 402a5be..84b4e54 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -23,43 +23,47 @@
###########################################################################
# Shared between CMakeLists.txt and Makefile.am
-LIB_CURLX_CFILES = \
- curlx/base64.c \
- curlx/dynbuf.c \
- curlx/fopen.c \
- curlx/inet_ntop.c \
- curlx/inet_pton.c \
- curlx/multibyte.c \
- curlx/nonblock.c \
- curlx/strcopy.c \
- curlx/strerr.c \
- curlx/strparse.c \
- curlx/timediff.c \
- curlx/timeval.c \
+LIB_CURLX_CFILES = \
+ curlx/base64.c \
+ curlx/basename.c \
+ curlx/dynbuf.c \
+ curlx/fopen.c \
+ curlx/inet_ntop.c \
+ curlx/inet_pton.c \
+ curlx/multibyte.c \
+ curlx/nonblock.c \
+ curlx/snprintf.c \
+ curlx/strcopy.c \
+ curlx/strdup.c \
+ curlx/strerr.c \
+ curlx/strparse.c \
+ curlx/timediff.c \
+ curlx/timeval.c \
curlx/version_win32.c \
- curlx/wait.c \
- curlx/warnless.c \
+ curlx/wait.c \
+ curlx/warnless.c \
curlx/winapi.c
-LIB_CURLX_HFILES = \
- curlx/binmode.h \
- curlx/base64.h \
- curlx/curlx.h \
- curlx/dynbuf.h \
- curlx/fopen.h \
- curlx/inet_ntop.h \
- curlx/inet_pton.h \
- curlx/multibyte.h \
- curlx/nonblock.h \
- curlx/snprintf.h \
- curlx/strcopy.h \
- curlx/strerr.h \
- curlx/strparse.h \
- curlx/timediff.h \
- curlx/timeval.h \
+LIB_CURLX_HFILES = \
+ curlx/base64.h \
+ curlx/basename.h \
+ curlx/curlx.h \
+ curlx/dynbuf.h \
+ curlx/fopen.h \
+ curlx/inet_ntop.h \
+ curlx/inet_pton.h \
+ curlx/multibyte.h \
+ curlx/nonblock.h \
+ curlx/snprintf.h \
+ curlx/strcopy.h \
+ curlx/strdup.h \
+ curlx/strerr.h \
+ curlx/strparse.h \
+ curlx/timediff.h \
+ curlx/timeval.h \
curlx/version_win32.h \
- curlx/wait.h \
- curlx/warnless.h \
+ curlx/wait.h \
+ curlx/warnless.h \
curlx/winapi.h
LIB_VAUTH_CFILES = \
@@ -116,24 +120,22 @@
vtls/wolfssl.h \
vtls/x509asn1.h
-LIB_VQUIC_CFILES = \
+LIB_VQUIC_CFILES = \
vquic/curl_ngtcp2.c \
- vquic/curl_osslq.c \
vquic/curl_quiche.c \
- vquic/vquic.c \
+ vquic/vquic.c \
vquic/vquic-tls.c
-LIB_VQUIC_HFILES = \
+LIB_VQUIC_HFILES = \
vquic/curl_ngtcp2.h \
- vquic/curl_osslq.h \
vquic/curl_quiche.h \
- vquic/vquic.h \
- vquic/vquic_int.h \
+ vquic/vquic.h \
+ vquic/vquic_int.h \
vquic/vquic-tls.h
-LIB_VSSH_CFILES = \
- vssh/libssh.c \
- vssh/libssh2.c \
+LIB_VSSH_CFILES = \
+ vssh/libssh.c \
+ vssh/libssh2.c \
vssh/vssh.c
LIB_VSSH_HFILES = \
@@ -252,7 +254,6 @@
socks_sspi.c \
splay.c \
strcase.c \
- strdup.c \
strequal.c \
strerror.c \
system_win32.c \
@@ -306,7 +307,6 @@
curl_rtmp.h \
curl_sasl.h \
curl_setup.h \
- curl_setup_once.h \
curl_sha256.h \
curl_sha512_256.h \
curl_share.h \
@@ -382,7 +382,6 @@
socks.h \
splay.h \
strcase.h \
- strdup.h \
strerror.h \
system_win32.h \
telnet.h \
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index 7006333..34da3e1 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -39,7 +39,7 @@
#include "connect.h"
#define MAX_ALTSVC_LINE 4095
-#define MAX_ALTSVC_DATELEN 256
+#define MAX_ALTSVC_DATELEN 17
#define MAX_ALTSVC_HOSTLEN 2048
#define MAX_ALTSVC_ALPNLEN 10
@@ -175,7 +175,7 @@
(size_t)srcport, (size_t)dstport);
if(as) {
as->expires = expires;
- as->prio = 0; /* not supported to just set zero */
+ as->prio = 0; /* not supported, set zero */
as->persist = persist ? 1 : 0;
Curl_llist_append(&asi->list, as, &as->node);
}
@@ -229,7 +229,6 @@
/*
* Write this single altsvc entry to a single output line
*/
-
static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
{
struct tm stamp;
@@ -310,10 +309,18 @@
/*
* Curl_altsvc_ctrl() passes on the external bitmask.
*/
-CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
+CURLcode Curl_altsvc_ctrl(struct Curl_easy *data, const long ctrl)
{
- DEBUGASSERT(asi);
- asi->flags = ctrl;
+ DEBUGASSERT(data);
+ if(!ctrl)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(!data->asi) {
+ data->asi = Curl_altsvc_init();
+ if(!data->asi)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->asi->flags = ctrl;
return CURLE_OK;
}
@@ -321,12 +328,12 @@
* Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
* resources.
*/
-void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
+void Curl_altsvc_cleanup(struct altsvcinfo **asi)
{
- if(*altsvcp) {
+ if(*asi) {
struct Curl_llist_node *e;
struct Curl_llist_node *n;
- struct altsvcinfo *altsvc = *altsvcp;
+ struct altsvcinfo *altsvc = *asi;
for(e = Curl_llist_head(&altsvc->list); e; e = n) {
struct altsvc *as = Curl_node_elem(e);
n = Curl_node_next(e);
@@ -334,7 +341,7 @@
}
curlx_free(altsvc->filename);
curlx_free(altsvc);
- *altsvcp = NULL; /* clear the pointer */
+ *asi = NULL; /* clear the pointer */
}
}
@@ -342,21 +349,21 @@
* Curl_altsvc_save() writes the altsvc cache to a file.
*/
CURLcode Curl_altsvc_save(struct Curl_easy *data,
- struct altsvcinfo *altsvc, const char *file)
+ struct altsvcinfo *asi, const char *file)
{
CURLcode result = CURLE_OK;
FILE *out;
char *tempstore = NULL;
- if(!altsvc)
+ if(!asi)
/* no cache activated */
return CURLE_OK;
/* if not new name is given, use the one we stored from the load */
- if(!file && altsvc->filename)
- file = altsvc->filename;
+ if(!file && asi->filename)
+ file = asi->filename;
- if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0])
+ if((asi->flags & CURLALTSVC_READONLYFILE) || !file || !file[0])
/* marked as read-only, no file or zero length filename */
return CURLE_OK;
@@ -367,7 +374,7 @@
fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
- for(e = Curl_llist_head(&altsvc->list); e; e = n) {
+ for(e = Curl_llist_head(&asi->list); e; e = n) {
struct altsvc *as = Curl_node_elem(e);
n = Curl_node_next(e);
result = altsvc_out(as, out);
@@ -459,9 +466,6 @@
unsigned short dstport = srcport; /* the same by default */
size_t entries = 0;
struct Curl_str alpn;
-#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)data;
-#endif
DEBUGASSERT(asi);
diff --git a/Utilities/cmcurl/lib/altsvc.h b/Utilities/cmcurl/lib/altsvc.h
index b82eaa8..2931af4 100644
--- a/Utilities/cmcurl/lib/altsvc.h
+++ b/Utilities/cmcurl/lib/altsvc.h
@@ -54,11 +54,11 @@
CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *asi, const char *file);
-CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
-void Curl_altsvc_cleanup(struct altsvcinfo **altsvc);
+CURLcode Curl_altsvc_ctrl(struct Curl_easy *data, const long ctrl);
+void Curl_altsvc_cleanup(struct altsvcinfo **asi);
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
- struct altsvcinfo *altsvc, const char *value,
- enum alpnid srcalpn, const char *srchost,
+ struct altsvcinfo *asi, const char *value,
+ enum alpnid srcalpnid, const char *srchost,
unsigned short srcport);
bool Curl_altsvc_lookup(struct altsvcinfo *asi,
enum alpnid srcalpnid, const char *srchost,
diff --git a/Utilities/cmcurl/lib/amigaos.c b/Utilities/cmcurl/lib/amigaos.c
index 7ce5045..d2afdbf 100644
--- a/Utilities/cmcurl/lib/amigaos.c
+++ b/Utilities/cmcurl/lib/amigaos.c
@@ -26,6 +26,7 @@
#ifdef __AMIGA__
#include "hostip.h"
+#include "curl_addrinfo.h"
#include "amigaos.h"
#ifdef HAVE_PROTO_BSDSOCKET_H
diff --git a/Utilities/cmcurl/lib/arpa_telnet.h b/Utilities/cmcurl/lib/arpa_telnet.h
index daf2487..b5faab4 100644
--- a/Utilities/cmcurl/lib/arpa_telnet.h
+++ b/Utilities/cmcurl/lib/arpa_telnet.h
@@ -27,19 +27,18 @@
/*
* Telnet option defines. Add more here if in need.
*/
-#define CURL_TELOPT_BINARY 0 /* binary 8bit data */
-#define CURL_TELOPT_ECHO 1 /* just echo! */
-#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */
-#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
-#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
-#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */
-#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
-
+#define CURL_TELOPT_BINARY 0 /* binary 8-bit data */
+#define CURL_TELOPT_ECHO 1 /* echo */
+#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */
+#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
+#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
+#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */
+#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
#define CURL_NEW_ENV_VAR 0
#define CURL_NEW_ENV_VALUE 1
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
/*
* The telnet options represented as strings
*/
@@ -55,9 +54,9 @@
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
-#define CURL_TELOPT(x) telnetoptions[x]
+#define CURL_TELOPT(x) telnetoptions[x]
#else
-#define CURL_TELOPT(x) ""
+#define CURL_TELOPT(x) ""
#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
@@ -81,7 +80,7 @@
#define CURL_DONT 254 /* DO NOT use this option! */
#define CURL_IAC 255 /* Interpret As Command */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
/*
* Then those numbers represented as strings:
*/
@@ -101,13 +100,14 @@
#define CURL_TELQUAL_INFO 2
#define CURL_TELQUAL_NAME 3
-#define CURL_TELCMD_OK(x) (((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
- ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM))
+#define CURL_TELCMD_OK(x) \
+ (((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
+ ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM))
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-#define CURL_TELCMD(x) telnetcmds[(x) - CURL_TELCMD_MINIMUM]
+#ifdef CURLVERBOSE
+#define CURL_TELCMD(x) telnetcmds[(x) - CURL_TELCMD_MINIMUM]
#else
-#define CURL_TELCMD(x) ""
+#define CURL_TELCMD(x) ""
#endif
#endif /* CURL_DISABLE_TELNET */
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index 7544140..4d063d9 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -47,6 +47,7 @@
#include "urldata.h"
#include "cfilters.h"
+#include "curl_addrinfo.h"
#include "curl_trc.h"
#include "hostip.h"
#include "url.h"
@@ -62,11 +63,6 @@
#include <ares_version.h> /* really old c-ares did not include this by
itself */
-#if ARES_VERSION >= 0x010601
-/* IPv6 supported since 1.6.1 */
-#define HAVE_CARES_IPV6 1
-#endif
-
#if ARES_VERSION >= 0x010704
#define HAVE_CARES_SERVERS_CSV 1
#define HAVE_CARES_LOCAL_DEV 1
@@ -308,7 +304,7 @@
(ares->happy_eyeballs_dns_time.tv_sec ||
ares->happy_eyeballs_dns_time.tv_usec) &&
(curlx_ptimediff_ms(Curl_pgrs_now(data),
- &ares->happy_eyeballs_dns_time) >=
+ &ares->happy_eyeballs_dns_time) >=
HAPPY_EYEBALLS_DNS_TIMEOUT)) {
/* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
running. */
@@ -331,13 +327,15 @@
result = ares->result;
if(ares->ares_status == ARES_SUCCESS && !result) {
data->state.async.dns =
- Curl_dnscache_mk_entry(data, ares->temp_ai,
+ Curl_dnscache_mk_entry(data, &ares->temp_ai,
data->state.async.hostname, 0,
data->state.async.port, FALSE);
- if(data->state.async.dns)
- ares->temp_ai = NULL; /* temp_ai now owned by entry */
+ if(!data->state.async.dns) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
#ifdef HTTPSRR_WORKS
- if(data->state.async.dns) {
+ {
struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo);
if(!lhrr)
result = CURLE_OUT_OF_MEMORY;
@@ -345,7 +343,7 @@
data->state.async.dns->hinfo = lhrr;
}
#endif
- if(!result && data->state.async.dns)
+ if(!result)
result = Curl_dnscache_add(data, data->state.async.dns);
}
/* if we have not found anything, report the proper
@@ -370,6 +368,32 @@
return result;
}
+static timediff_t async_ares_poll_timeout(struct async_ares_ctx *ares,
+ timediff_t timeout_ms)
+{
+ struct timeval *ares_calced, time_buf, max_timeout;
+ int itimeout_ms;
+
+#if TIMEDIFF_T_MAX > INT_MAX
+ itimeout_ms = (timeout_ms > INT_MAX) ? INT_MAX :
+ ((timeout_ms < 0) ? -1 : (int)timeout_ms);
+#else
+ itimeout_ms = (int)timeout_ms;
+#endif
+ max_timeout.tv_sec = itimeout_ms / 1000;
+ max_timeout.tv_usec = (itimeout_ms % 1000) * 1000;
+
+ /* c-ares tells us the shortest timeout of any operation on channel */
+ ares_calced = ares_timeout(ares->channel, &max_timeout, &time_buf);
+ /* use the timeout period ares returned to us above if less than one
+ second is left, otherwise use 1000ms to make sure the progress callback
+ gets called frequent enough */
+ if(!ares_calced->tv_sec)
+ return (timediff_t)(ares_calced->tv_usec / 1000);
+ else
+ return 1000;
+}
+
/*
* Curl_async_await()
*
@@ -382,76 +406,53 @@
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
CURLcode Curl_async_await(struct Curl_easy *data,
- struct Curl_dns_entry **entry)
+ struct Curl_dns_entry **dns)
{
struct async_ares_ctx *ares = &data->state.async.ares;
+ struct curltime start = *Curl_pgrs_now(data);
CURLcode result = CURLE_OK;
- timediff_t timeout_ms;
- DEBUGASSERT(entry);
- *entry = NULL; /* clear on entry */
+ DEBUGASSERT(dns);
+ *dns = NULL; /* clear on entry */
- timeout_ms = Curl_timeleft_ms(data, TRUE);
- if(timeout_ms < 0) {
- /* already expired! */
- connclose(data->conn, "Timed out before name resolve started");
- return CURLE_OPERATION_TIMEDOUT;
- }
- if(!timeout_ms)
- timeout_ms = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve */
-
- /* Wait for the name resolve query to complete. */
+ /* Wait for the name resolve query to complete or time out. */
while(!result) {
- struct timeval *real_timeout, time_buf, max_timeout;
- int itimeout_ms;
- timediff_t call_timeout_ms;
+ timediff_t timeout_ms;
-#if TIMEDIFF_T_MAX > INT_MAX
- itimeout_ms = (timeout_ms > INT_MAX) ? INT_MAX : (int)timeout_ms;
-#else
- itimeout_ms = (int)timeout_ms;
-#endif
+ timeout_ms = Curl_timeleft_ms(data);
+ if(!timeout_ms) { /* no applicable timeout from `data`*/
+ timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &start);
+ if(elapsed_ms < (CURL_TIMEOUT_RESOLVE * 1000))
+ timeout_ms = (CURL_TIMEOUT_RESOLVE * 1000) - elapsed_ms;
+ else
+ timeout_ms = -1;
+ }
- max_timeout.tv_sec = itimeout_ms / 1000;
- max_timeout.tv_usec = (itimeout_ms % 1000) * 1000;
+ if(timeout_ms < 0) {
+ result = CURLE_OPERATION_TIMEDOUT;
+ break;
+ }
- real_timeout = ares_timeout(ares->channel, &max_timeout, &time_buf);
+ if(Curl_ares_perform(ares->channel,
+ async_ares_poll_timeout(ares, timeout_ms)) < 0) {
+ result = CURLE_UNRECOVERABLE_POLL;
+ break;
+ }
- /* use the timeout period ares returned to us above if less than one
- second is left, otherwise just use 1000ms to make sure the progress
- callback gets called frequent enough */
- if(!real_timeout->tv_sec)
- call_timeout_ms = (timediff_t)(real_timeout->tv_usec / 1000);
- else
- call_timeout_ms = 1000;
-
- if(Curl_ares_perform(ares->channel, call_timeout_ms) < 0)
- return CURLE_UNRECOVERABLE_POLL;
-
- result = Curl_async_is_resolved(data, entry);
+ result = Curl_async_is_resolved(data, dns);
if(result || data->state.async.done)
break;
- if(Curl_pgrsUpdate(data))
+ if(Curl_pgrsUpdate(data)) {
result = CURLE_ABORTED_BY_CALLBACK;
- else {
- struct curltime now = curlx_now(); /* update in loop */
- timediff_t elapsed_ms = curlx_ptimediff_ms(&now, Curl_pgrs_now(data));
- if(elapsed_ms <= 0)
- timeout_ms -= 1; /* always deduct at least 1 */
- else if(elapsed_ms > timeout_ms)
- timeout_ms = -1;
- else
- timeout_ms -= elapsed_ms;
+ break;
}
- if(timeout_ms < 0)
- result = CURLE_OPERATION_TIMEDOUT;
}
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
data->state.async.done = TRUE;
- *entry = data->state.async.dns;
+ *dns = data->state.async.dns;
if(result)
ares_cancel(ares->channel);
@@ -546,12 +547,11 @@
talking to a pool of DNS servers that can only successfully resolve
IPv4 address, for example).
- it is also possible that the other request could always just take
- longer because it needs more time or only the second DNS server can
- fulfill it successfully. But, to align with the philosophy of Happy
- Eyeballs, we do not want to wait _too_ long or users will think
- requests are slow when IPv6 lookups do not actually work (but IPv4
- ones do).
+ it is also possible that the other request could always take longer
+ because it needs more time or only the second DNS server can fulfill it
+ successfully. But, to align with the philosophy of Happy Eyeballs, we
+ do not want to wait _too_ long or users will think requests are slow
+ when IPv6 lookups do not actually work (but IPv4 ones do).
So, now that we have a usable answer (some IPv4 addresses, some IPv6
addresses, or "no such domain"), we start a timeout for the remaining
@@ -559,24 +559,23 @@
request came back quickly, that need not be the case. It might be that
this completing request did not get a result from the first DNS
server or even the first round of the whole DNS server pool. So it
- could already be quite some time after we issued the DNS queries in
+ could already be a long time after we issued the DNS queries in
the first place. Without modifying c-ares, we cannot know exactly
where in its retry cycle we are. We could guess based on how much
time has gone by, but it does not really matter. Happy Eyeballs tells
- us that, given usable information in hand, we simply do not want to
+ us that, given usable information in hand, we do not want to
wait "too much longer" after we get a result.
- We simply wait an additional amount of time equal to the default
- c-ares query timeout. That is enough time for a typical parallel
- response to arrive without being "too long". Even on a network
- where one of the two types of queries is failing or timing out
- constantly, this will usually mean we wait a total of the default
- c-ares timeout (5 seconds) plus the round trip time for the successful
- request, which seems bearable. The downside is that c-ares might race
- with us to issue one more retry just before we give up, but it seems
- better to "waste" that request instead of trying to guess the perfect
- timeout to prevent it. After all, we do not even know where in the
- c-ares retry cycle each request is.
+ We wait an additional amount of time equal to the default c-ares
+ query timeout. That is enough time for a typical parallel response to
+ arrive without being "too long". Even on a network where one of the two
+ types of queries is failing or timing out constantly, this will usually
+ mean we wait a total of the default c-ares timeout (5 seconds) plus the
+ round trip time for the successful request, which seems bearable. The
+ downside is that c-ares might race with us to issue one more retry
+ before we give up, but it seems better to "waste" that request instead
+ of trying to guess the perfect timeout to prevent it. After all, we do
+ not even know where in the c-ares retry cycle each request is.
*/
ares->happy_eyeballs_dns_time = *Curl_pgrs_now(data);
Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
@@ -602,8 +601,8 @@
for(ai = node; ai != NULL; ai = ai->ai_next) {
size_t ss_size;
struct Curl_addrinfo *ca;
- /* ignore elements with unsupported address family, */
- /* settle family-specific sockaddr structure size. */
+ /* ignore elements with unsupported address family,
+ settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
#ifdef USE_IPV6
@@ -627,8 +626,8 @@
break;
}
- /* copy each structure member individually, member ordering, */
- /* size, or padding might be different for each platform. */
+ /* copy each structure member individually, member ordering,
+ size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
@@ -739,8 +738,7 @@
ares->ares_status = ARES_ENOTFOUND;
ares->result = CURLE_OK;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS) && \
- ARES_VERSION >= 0x011800 /* >= v1.24.0 */
+#if defined(CURLVERBOSE) && ARES_VERSION >= 0x011800 /* >= v1.24.0 */
if(CURL_TRC_DNS_is_verbose(data)) {
char *csv = ares_get_servers_csv(ares->channel);
CURL_TRC_DNS(data, "asyn-ares: servers=%s", csv);
@@ -755,8 +753,7 @@
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if((ip_version != CURL_IPRESOLVE_V4) &&
- Curl_ipv6works(data)) {
+ if((ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
if(ip_version == CURL_IPRESOLVE_V6)
pf = PF_INET6;
@@ -782,7 +779,7 @@
}
#else
-#ifdef HAVE_CARES_IPV6
+#if ARES_VERSION >= 0x010601 /* IPv6 supported since 1.6.1 */
if((ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
/* areschannel is already setup in the Curl_open() function */
@@ -836,7 +833,7 @@
const char *servers = data->set.str[STRING_DNS_SERVERS];
int ares_result = ARES_SUCCESS;
-#if defined(CURLDEBUG) && defined(HAVE_CARES_SERVERS_CSV)
+#if defined(DEBUGBUILD) && defined(HAVE_CARES_SERVERS_CSV)
if(getenv("CURL_DNS_SERVER"))
servers = getenv("CURL_DNS_SERVER");
#endif
@@ -849,7 +846,7 @@
}
#ifdef HAVE_CARES_SERVERS_CSV
- /* if channel is not there, this is just a parameter check */
+ /* if channel is not there, this is a parameter check */
if(ares->channel)
#ifdef HAVE_CARES_PORTS_CSV
ares_result = ares_set_servers_ports_csv(ares->channel, servers);
@@ -892,7 +889,7 @@
if(!interf)
interf = "";
- /* if channel is not there, this is just a parameter check */
+ /* if channel is not there, this is a parameter check */
if(ares->channel)
ares_set_local_dev(ares->channel, interf);
@@ -911,7 +908,7 @@
struct in_addr a4;
const char *local_ip4 = data->set.str[STRING_DNS_LOCAL_IP4];
- if((!local_ip4) || (local_ip4[0] == 0)) {
+ if(!local_ip4 || (local_ip4[0] == 0)) {
a4.s_addr = 0; /* disabled: do not bind to a specific address */
}
else {
@@ -921,7 +918,7 @@
}
}
- /* if channel is not there yet, this is just a parameter check */
+ /* if channel is not there yet, this is a parameter check */
if(ares->channel)
ares_set_local_ip4(ares->channel, ntohl(a4.s_addr));
@@ -940,7 +937,7 @@
unsigned char a6[INET6_ADDRSTRLEN];
const char *local_ip6 = data->set.str[STRING_DNS_LOCAL_IP6];
- if((!local_ip6) || (local_ip6[0] == 0)) {
+ if(!local_ip6 || (local_ip6[0] == 0)) {
/* disabled: do not bind to a specific address */
memset(a6, 0, sizeof(a6));
}
@@ -951,7 +948,7 @@
}
}
- /* if channel is not there, this is just a parameter check */
+ /* if channel is not there, this is a parameter check */
if(ares->channel)
ares_set_local_ip6(ares->channel, a6);
diff --git a/Utilities/cmcurl/lib/asyn-base.c b/Utilities/cmcurl/lib/asyn-base.c
index 02797f1..44bf98c 100644
--- a/Utilities/cmcurl/lib/asyn-base.c
+++ b/Utilities/cmcurl/lib/asyn-base.c
@@ -43,7 +43,6 @@
#endif
#include "urldata.h"
-#include "asyn.h"
#include "hostip.h"
#include "multiif.h"
#include "select.h"
@@ -156,7 +155,7 @@
nfds = 0;
if(!nfds)
- /* Call ares_process() unconditionally here, even if we simply timed out
+ /* Call ares_process() unconditionally here, even if we timed out
above, as otherwise the ares name resolve will not timeout! */
ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
else {
diff --git a/Utilities/cmcurl/lib/asyn-thrdd.c b/Utilities/cmcurl/lib/asyn-thrdd.c
index 690e813..c3ed8ea 100644
--- a/Utilities/cmcurl/lib/asyn-thrdd.c
+++ b/Utilities/cmcurl/lib/asyn-thrdd.c
@@ -56,8 +56,10 @@
#include "urldata.h"
#include "cfilters.h"
+#include "curl_addrinfo.h"
#include "curl_trc.h"
#include "hostip.h"
+#include "httpsrr.h"
#include "url.h"
#include "multiif.h"
#include "curl_threads.h"
@@ -99,8 +101,8 @@
#endif
}
-static void async_thrdd_destroy(struct Curl_easy *);
-static void async_thrdd_shutdown(struct Curl_easy *);
+static void async_thrdd_destroy(struct Curl_easy *data);
+static void async_thrdd_shutdown(struct Curl_easy *data);
CURLcode Curl_async_get_impl(struct Curl_easy *data, void **impl)
{
@@ -116,7 +118,6 @@
struct async_thrdd_addr_ctx *addr_ctx = *paddr_ctx;
bool destroy;
- (void)data;
if(!addr_ctx)
return;
@@ -134,12 +135,7 @@
curlx_free(addr_ctx->hostname);
if(addr_ctx->res)
Curl_freeaddrinfo(addr_ctx->res);
-#ifndef CURL_DISABLE_SOCKETPAIR
-#ifndef USE_EVENTFD
- wakeup_close(addr_ctx->sock_pair[1]);
-#endif
- wakeup_close(addr_ctx->sock_pair[0]);
-#endif
+ Curl_wakeup_destroy(addr_ctx->sock_pair);
curlx_free(addr_ctx);
}
*paddr_ctx = NULL;
@@ -170,7 +166,7 @@
#ifndef CURL_DISABLE_SOCKETPAIR
/* create socket pair or pipe */
- if(wakeup_create(addr_ctx->sock_pair, FALSE) < 0) {
+ if(Curl_wakeup_init(addr_ctx->sock_pair, FALSE) < 0) {
addr_ctx->sock_pair[0] = CURL_SOCKET_BAD;
addr_ctx->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
@@ -203,7 +199,7 @@
static CURL_THREAD_RETURN_T CURL_STDCALL getaddrinfo_thread(void *arg)
{
struct async_thrdd_addr_ctx *addr_ctx = arg;
- bool do_abort;
+ curl_bit do_abort;
Curl_mutex_acquire(&addr_ctx->mutx);
do_abort = addr_ctx->do_abort;
@@ -232,15 +228,11 @@
Curl_mutex_release(&addr_ctx->mutx);
#ifndef CURL_DISABLE_SOCKETPAIR
if(!do_abort) {
-#ifdef USE_EVENTFD
- const uint64_t buf[1] = { 1 };
-#else
- const char buf[1] = { 1 };
-#endif
/* Thread is done, notify transfer */
- if(wakeup_write(addr_ctx->sock_pair[1], buf, sizeof(buf)) < 0) {
+ int err = Curl_wakeup_signal(addr_ctx->sock_pair);
+ if(err) {
/* update sock_error to errno */
- addr_ctx->sock_error = SOCKERRNO;
+ addr_ctx->sock_error = err;
}
}
#endif
@@ -277,15 +269,10 @@
Curl_mutex_release(&addr_ctx->mutx);
#ifndef CURL_DISABLE_SOCKETPAIR
if(!do_abort) {
-#ifdef USE_EVENTFD
- const uint64_t buf[1] = { 1 };
-#else
- const char buf[1] = { 1 };
-#endif
- /* Thread is done, notify transfer */
- if(wakeup_write(addr_ctx->sock_pair[1], buf, sizeof(buf)) < 0) {
+ int err = Curl_wakeup_signal(addr_ctx->sock_pair);
+ if(err) {
/* update sock_error to errno */
- addr_ctx->sock_error = SOCKERRNO;
+ addr_ctx->sock_error = err;
}
}
#endif
@@ -314,7 +301,7 @@
#endif
if(thrdd->addr && (thrdd->addr->thread_hnd != curl_thread_t_null)) {
- bool done;
+ curl_bit done;
Curl_mutex_acquire(&addr->mutx);
#ifndef CURL_DISABLE_SOCKETPAIR
@@ -373,7 +360,7 @@
curlx_free(rrname);
return CURLE_FAILED_INIT;
}
-#ifdef CURLDEBUG
+#ifdef DEBUGBUILD
if(getenv("CURL_DNS_SERVER")) {
const char *servers = getenv("CURL_DNS_SERVER");
status = ares_set_servers_ports_csv(thrdd->rr.channel, servers);
@@ -475,7 +462,7 @@
{
struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
struct async_thrdd_addr_ctx *addr_ctx = thrdd->addr;
- bool done;
+ curl_bit done;
if(!addr_ctx)
return;
@@ -534,7 +521,7 @@
/*
* Until we gain a way to signal the resolver threads to stop early, we must
- * simply wait for them and ignore their results.
+ * wait for them and ignore their results.
*/
void Curl_async_thrdd_shutdown(struct Curl_easy *data)
{
@@ -565,11 +552,11 @@
* This is the version for resolves-in-a-thread.
*/
CURLcode Curl_async_await(struct Curl_easy *data,
- struct Curl_dns_entry **entry)
+ struct Curl_dns_entry **dns)
{
struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
if(thrdd->addr)
- return asyn_thrdd_await(data, thrdd->addr, entry);
+ return asyn_thrdd_await(data, thrdd->addr, dns);
return CURLE_FAILED_INIT;
}
@@ -582,7 +569,7 @@
struct Curl_dns_entry **dns)
{
struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
- bool done = FALSE;
+ curl_bit done = FALSE;
DEBUGASSERT(dns);
*dns = NULL;
@@ -617,10 +604,9 @@
if(thrdd->addr->res) {
data->state.async.dns =
- Curl_dnscache_mk_entry(data, thrdd->addr->res,
+ Curl_dnscache_mk_entry(data, &thrdd->addr->res,
data->state.async.hostname, 0,
data->state.async.port, FALSE);
- thrdd->addr->res = NULL;
if(!data->state.async.dns)
result = CURLE_OUT_OF_MEMORY;
@@ -679,7 +665,7 @@
{
struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
CURLcode result = CURLE_OK;
- bool thrd_done;
+ curl_bit thrd_done;
#if !defined(USE_HTTPSRR_ARES) && defined(CURL_DISABLE_SOCKETPAIR)
(void)ps;
diff --git a/Utilities/cmcurl/lib/asyn.h b/Utilities/cmcurl/lib/asyn.h
index b961081..68628f9 100644
--- a/Utilities/cmcurl/lib/asyn.h
+++ b/Utilities/cmcurl/lib/asyn.h
@@ -25,15 +25,17 @@
***************************************************************************/
#include "curl_setup.h"
+#if defined(USE_HTTPSRR) && defined(USE_ARES)
+#include "httpsrr.h"
+#endif
+
struct Curl_easy;
struct Curl_dns_entry;
#ifdef CURLRES_ASYNCH
#include "curl_addrinfo.h"
-#include "httpsrr.h"
-struct addrinfo;
struct hostent;
struct connectdata;
struct easy_pollset;
@@ -68,7 +70,7 @@
* Get the resolver implementation instance (c-ares channel) or NULL
* for passing to application callback.
*/
-CURLcode Curl_async_get_impl(struct Curl_easy *easy, void **impl);
+CURLcode Curl_async_get_impl(struct Curl_easy *data, void **impl);
/* Curl_async_pollset()
*
@@ -104,7 +106,7 @@
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
CURLcode Curl_async_await(struct Curl_easy *data,
- struct Curl_dns_entry **dnsentry);
+ struct Curl_dns_entry **dns);
/*
* Curl_async_getaddrinfo() - when using this resolver
diff --git a/Utilities/cmcurl/lib/bufq.h b/Utilities/cmcurl/lib/bufq.h
index bcd7df2..8dd186f 100644
--- a/Utilities/cmcurl/lib/bufq.h
+++ b/Utilities/cmcurl/lib/bufq.h
@@ -44,9 +44,8 @@
/**
* A pool for providing/keeping a number of chunks of the same size
*
- * The same pool can be shared by many `bufq` instances. However, a pool
- * is not thread safe. All bufqs using it are supposed to operate in the
- * same thread.
+ * The same pool can be shared by many `bufq` instances. A pool is not thread
+ * safe. All bufqs using it are supposed to operate in the same thread.
*/
struct bufc_pool {
struct buf_chunk *spare; /* list of available spare chunks */
@@ -77,10 +76,10 @@
*
* By default, writing to a full bufq will return (-1, CURLE_AGAIN). Same
* as reading from an empty bufq.
- * With `BUFQ_OPT_SOFT_LIMIT` set, a bufq will allow writing becond this
- * limit and use more than `max_chunks`. However it will report that it
- * is full nevertheless. This is provided for situation where writes
- * preferably never fail (except for memory exhaustion).
+ * With `BUFQ_OPT_SOFT_LIMIT` set, a bufq will allow writing beyond this limit
+ * and use more than `max_chunks`. It will report that it is full
+ * nevertheless. This is provided for situation where writes preferably never
+ * fail (except for memory exhaustion).
*
* By default and without a pool, a bufq will keep chunks that read
* empty in its `spare` list. Option `BUFQ_OPT_NO_SPARES` will
@@ -104,7 +103,7 @@
* Default behaviour: chunk limit is "hard", meaning attempts to write
* more bytes than can be hold in `max_chunks` is refused and will return
* -1, CURLE_AGAIN. */
-#define BUFQ_OPT_NONE (0)
+#define BUFQ_OPT_NONE 0
/**
* Make `max_chunks` a "soft" limit. A bufq will report that it is "full"
* when `max_chunks` are used, but allows writing beyond this limit.
@@ -197,9 +196,8 @@
const uint8_t **pbuf, size_t *plen);
/**
- * Tell the buffer queue to discard `amount` buf bytes at the head
- * of the queue. Skipping more buf than is currently buffered will
- * just empty the queue.
+ * Tell the buffer queue to discard `amount` buf bytes at the head of the
+ * queue. Skipping more buf than is currently buffered will empty the queue.
*/
void Curl_bufq_skip(struct bufq *q, size_t amount);
diff --git a/Utilities/cmcurl/lib/bufref.c b/Utilities/cmcurl/lib/bufref.c
index b1272d5..50fafda 100644
--- a/Utilities/cmcurl/lib/bufref.c
+++ b/Utilities/cmcurl/lib/bufref.c
@@ -25,7 +25,7 @@
#include "urldata.h"
#include "bufref.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#ifdef DEBUGBUILD
#define SIGNATURE 0x5c48e9b2 /* Random pattern. */
@@ -128,7 +128,7 @@
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
if(ptr) {
- cpy = Curl_memdup0(ptr, len);
+ cpy = curlx_memdup0(ptr, len);
if(!cpy)
return CURLE_OUT_OF_MEMORY;
}
diff --git a/Utilities/cmcurl/lib/cf-h1-proxy.c b/Utilities/cmcurl/lib/cf-h1-proxy.c
index c41a68d..69e050b 100644
--- a/Utilities/cmcurl/lib/cf-h1-proxy.c
+++ b/Utilities/cmcurl/lib/cf-h1-proxy.c
@@ -31,7 +31,6 @@
#include "http.h"
#include "http1.h"
#include "http_proxy.h"
-#include "url.h"
#include "select.h"
#include "progress.h"
#include "cfilters.h"
@@ -39,7 +38,6 @@
#include "connect.h"
#include "curl_trc.h"
#include "strcase.h"
-#include "transfer.h"
#include "curlx/strparse.h"
@@ -106,8 +104,8 @@
{
struct h1_tunnel_state *ts;
- if(cf->conn->handler->flags & PROTOPT_NOTCPPROXY) {
- failf(data, "%s cannot be done over CONNECT", cf->conn->handler->scheme);
+ if(cf->conn->scheme->flags & PROTOPT_NOTCPPROXY) {
+ failf(data, "%s cannot be done over CONNECT", cf->conn->scheme->name);
return CURLE_UNSUPPORTED_PROTOCOL;
}
@@ -208,9 +206,8 @@
int http_minor;
CURLcode result;
- /* This only happens if we have looped here due to authentication
- reasons, and we do not really use the newly cloned URL here
- then. Just free it. */
+ /* This only happens if we have looped here due to authentication reasons,
+ and we do not really use the newly cloned URL here then. Free it. */
Curl_safefree(data->req.newurl);
result = Curl_http_proxy_create_CONNECT(&req, cf, data, 1);
@@ -241,7 +238,7 @@
struct h1_tunnel_state *ts,
bool *done)
{
- uint8_t *buf = curlx_dyn_uptr(&ts->request_data);
+ const uint8_t *buf = curlx_dyn_uptr(&ts->request_data);
size_t request_len = curlx_dyn_len(&ts->request_data);
size_t blen = request_len;
CURLcode result = CURLE_OK;
@@ -262,7 +259,7 @@
DEBUGASSERT(blen >= nwritten);
ts->nsent += nwritten;
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)buf, nwritten);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (const char *)buf, nwritten);
out:
if(result)
@@ -342,8 +339,8 @@
ISDIGIT(header[9]) && ISDIGIT(header[10]) && ISDIGIT(header[11]) &&
!ISDIGIT(header[12])) {
/* store the HTTP code from the proxy */
- data->info.httpproxycode = k->httpcode = (header[9] - '0') * 100 +
- (header[10] - '0') * 10 + (header[11] - '0');
+ data->info.httpproxycode = k->httpcode = ((header[9] - '0') * 100) +
+ ((header[10] - '0') * 10) + (header[11] - '0');
}
return result;
}
@@ -353,9 +350,9 @@
struct h1_tunnel_state *ts)
{
CURLcode result = CURLE_OK;
- char *linep = curlx_dyn_ptr(&ts->rcvbuf);
+ const char *linep = curlx_dyn_ptr(&ts->rcvbuf);
size_t line_len = curlx_dyn_len(&ts->rcvbuf); /* bytes in this line */
- struct SingleRequest *k = &data->req;
+ const struct SingleRequest *k = &data->req;
int writetype;
ts->headerlines++;
@@ -470,7 +467,7 @@
/* This means we are currently ignoring a response-body */
if(ts->cl) {
- /* A Content-Length based body: simply count down the counter
+ /* A Content-Length based body: count down the counter
and make sure to break out of the loop when we are done! */
ts->cl--;
if(ts->cl <= 0) {
@@ -531,7 +528,7 @@
if(byte != 0x0a)
continue;
else {
- char *linep = curlx_dyn_ptr(&ts->rcvbuf);
+ const char *linep = curlx_dyn_ptr(&ts->rcvbuf);
size_t hlen = curlx_dyn_len(&ts->rcvbuf);
if(hlen && ISNEWLINE(linep[0])) {
/* end of headers */
@@ -571,7 +568,7 @@
do {
- if(Curl_timeleft_ms(data, TRUE) < 0) {
+ if(Curl_timeleft_ms(data) < 0) {
failf(data, "Proxy CONNECT aborted due to timeout");
result = CURLE_OPERATION_TIMEDOUT;
goto out;
diff --git a/Utilities/cmcurl/lib/cf-h1-proxy.h b/Utilities/cmcurl/lib/cf-h1-proxy.h
index e48d827..6544ec5 100644
--- a/Utilities/cmcurl/lib/cf-h1-proxy.h
+++ b/Utilities/cmcurl/lib/cf-h1-proxy.h
@@ -27,7 +27,7 @@
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
-CURLcode Curl_cf_h1_proxy_insert_after(struct Curl_cfilter *cf,
+CURLcode Curl_cf_h1_proxy_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data);
extern struct Curl_cftype Curl_cft_h1_proxy;
diff --git a/Utilities/cmcurl/lib/cf-h2-proxy.c b/Utilities/cmcurl/lib/cf-h2-proxy.c
index 4f101a0..4275e1e 100644
--- a/Utilities/cmcurl/lib/cf-h2-proxy.c
+++ b/Utilities/cmcurl/lib/cf-h2-proxy.c
@@ -226,8 +226,7 @@
if(cf) {
struct Curl_easy *data = CF_DATA_CURRENT(cf);
CURLcode result;
- result = Curl_conn_cf_send(cf->next, data, buf, buflen,
- FALSE, pnwritten);
+ result = Curl_conn_cf_send(cf->next, data, buf, buflen, FALSE, pnwritten);
CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %d, %zu",
buflen, result, *pnwritten);
return result;
@@ -259,113 +258,6 @@
return rc;
}
-static ssize_t on_session_send(nghttp2_session *h2,
- const uint8_t *buf, size_t blen,
- int flags, void *userp);
-static int proxy_h2_on_frame_recv(nghttp2_session *session,
- const nghttp2_frame *frame,
- void *userp);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static int proxy_h2_on_frame_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- void *userp);
-#endif
-static int proxy_h2_on_stream_close(nghttp2_session *session,
- int32_t stream_id,
- uint32_t error_code, void *userp);
-static int proxy_h2_on_header(nghttp2_session *session,
- const nghttp2_frame *frame,
- const uint8_t *name, size_t namelen,
- const uint8_t *value, size_t valuelen,
- uint8_t flags,
- void *userp);
-static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags,
- int32_t stream_id,
- const uint8_t *mem, size_t len, void *userp);
-
-/*
- * Initialize the cfilter context
- */
-static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_h2_proxy_ctx *ctx = cf->ctx;
- CURLcode result = CURLE_OUT_OF_MEMORY;
- nghttp2_session_callbacks *cbs = NULL;
- int rc;
-
- DEBUGASSERT(!ctx->h2);
- memset(&ctx->tunnel, 0, sizeof(ctx->tunnel));
-
- Curl_bufq_init(&ctx->inbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
- Curl_bufq_init(&ctx->outbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
-
- if(tunnel_stream_init(cf, &ctx->tunnel))
- goto out;
-
- rc = nghttp2_session_callbacks_new(&cbs);
- if(rc) {
- failf(data, "Could not initialize nghttp2 callbacks");
- goto out;
- }
-
- nghttp2_session_callbacks_set_send_callback(cbs, on_session_send);
- nghttp2_session_callbacks_set_on_frame_recv_callback(
- cbs, proxy_h2_on_frame_recv);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- nghttp2_session_callbacks_set_on_frame_send_callback(cbs,
- proxy_h2_on_frame_send);
-#endif
- nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
- cbs, tunnel_recv_callback);
- nghttp2_session_callbacks_set_on_stream_close_callback(
- cbs, proxy_h2_on_stream_close);
- nghttp2_session_callbacks_set_on_header_callback(cbs, proxy_h2_on_header);
-
- /* The nghttp2 session is not yet setup, do it */
- rc = proxy_h2_client_new(cf, cbs);
- if(rc) {
- failf(data, "Could not initialize nghttp2");
- goto out;
- }
-
- {
- nghttp2_settings_entry iv[3];
-
- iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
- iv[0].value = Curl_multi_max_concurrent_streams(data->multi);
- iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
- iv[1].value = H2_TUNNEL_WINDOW_SIZE;
- iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
- iv[2].value = 0;
- rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE, iv, 3);
- if(rc) {
- failf(data, "nghttp2_submit_settings() failed: %s(%d)",
- nghttp2_strerror(rc), rc);
- result = CURLE_HTTP2;
- goto out;
- }
- }
-
- rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0,
- PROXY_HTTP2_HUGE_WINDOW_SIZE);
- if(rc) {
- failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
- nghttp2_strerror(rc), rc);
- result = CURLE_HTTP2;
- goto out;
- }
-
- /* all set, traffic will be send on connect */
- result = CURLE_OK;
-
-out:
- if(cbs)
- nghttp2_session_callbacks_del(cbs);
- CURL_TRC_CF(data, cf, "[0] init proxy ctx -> %d", result);
- return result;
-}
-
static int proxy_h2_should_close_session(struct cf_h2_proxy_ctx *ctx)
{
return !nghttp2_session_want_read(ctx->h2) &&
@@ -379,7 +271,6 @@
size_t nwritten;
CURLcode result;
- (void)data;
if(Curl_bufq_is_empty(&ctx->outbufq))
return CURLE_OK;
@@ -530,82 +421,11 @@
if(!nwritten)
return NGHTTP2_ERR_WOULDBLOCK;
- return (nwritten > SSIZE_MAX) ?
+ return (nwritten > SSIZE_MAX) ?
NGHTTP2_ERR_CALLBACK_FAILURE : (ssize_t)nwritten;
}
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static int proxy_h2_fr_print(const nghttp2_frame *frame,
- char *buffer, size_t blen)
-{
- switch(frame->hd.type) {
- case NGHTTP2_DATA: {
- return curl_msnprintf(buffer, blen,
- "FRAME[DATA, len=%d, eos=%d, padlen=%d]",
- (int)frame->hd.length,
- !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM),
- (int)frame->data.padlen);
- }
- case NGHTTP2_HEADERS: {
- return curl_msnprintf(buffer, blen,
- "FRAME[HEADERS, len=%d, hend=%d, eos=%d]",
- (int)frame->hd.length,
- !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
- !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
- }
- case NGHTTP2_PRIORITY: {
- return curl_msnprintf(buffer, blen,
- "FRAME[PRIORITY, len=%d, flags=%d]",
- (int)frame->hd.length, frame->hd.flags);
- }
- case NGHTTP2_RST_STREAM: {
- return curl_msnprintf(buffer, blen,
- "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]",
- (int)frame->hd.length, frame->hd.flags,
- frame->rst_stream.error_code);
- }
- case NGHTTP2_SETTINGS: {
- if(frame->hd.flags & NGHTTP2_FLAG_ACK) {
- return curl_msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]");
- }
- return curl_msnprintf(buffer, blen,
- "FRAME[SETTINGS, len=%d]", (int)frame->hd.length);
- }
- case NGHTTP2_PUSH_PROMISE:
- return curl_msnprintf(buffer, blen,
- "FRAME[PUSH_PROMISE, len=%d, hend=%d]",
- (int)frame->hd.length,
- !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS));
- case NGHTTP2_PING:
- return curl_msnprintf(buffer, blen,
- "FRAME[PING, len=%d, ack=%d]",
- (int)frame->hd.length,
- frame->hd.flags & NGHTTP2_FLAG_ACK);
- case NGHTTP2_GOAWAY: {
- char scratch[128];
- size_t s_len = CURL_ARRAYSIZE(scratch);
- size_t len = (frame->goaway.opaque_data_len < s_len) ?
- frame->goaway.opaque_data_len : s_len-1;
- if(len)
- memcpy(scratch, frame->goaway.opaque_data, len);
- scratch[len] = '\0';
- return curl_msnprintf(buffer, blen,
- "FRAME[GOAWAY, error=%d, reason='%s', "
- "last_stream=%d]", frame->goaway.error_code,
- scratch, frame->goaway.last_stream_id);
- }
- case NGHTTP2_WINDOW_UPDATE: {
- return curl_msnprintf(buffer, blen,
- "FRAME[WINDOW_UPDATE, incr=%d]",
- frame->window_update.window_size_increment);
- }
- default:
- return curl_msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]",
- frame->hd.type, (int)frame->hd.length,
- frame->hd.flags);
- }
-}
-
+#ifdef CURLVERBOSE
static int proxy_h2_on_frame_send(nghttp2_session *session,
const nghttp2_frame *frame,
void *userp)
@@ -615,16 +435,16 @@
(void)session;
DEBUGASSERT(data);
- if(data && Curl_trc_cf_is_verbose(cf, data)) {
+ if(Curl_trc_cf_is_verbose(cf, data)) {
char buffer[256];
int len;
- len = proxy_h2_fr_print(frame, buffer, sizeof(buffer) - 1);
+ len = Curl_nghttp2_fr_print(frame, buffer, sizeof(buffer) - 1);
buffer[len] = 0;
CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
}
return 0;
}
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* CURLVERBOSE */
static int proxy_h2_on_frame_recv(nghttp2_session *session,
const nghttp2_frame *frame,
@@ -637,15 +457,15 @@
(void)session;
DEBUGASSERT(data);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
if(Curl_trc_cf_is_verbose(cf, data)) {
char buffer[256];
int len;
- len = proxy_h2_fr_print(frame, buffer, sizeof(buffer) - 1);
+ len = Curl_nghttp2_fr_print(frame, buffer, sizeof(buffer) - 1);
buffer[len] = 0;
CURL_TRC_CF(data, cf, "[%d] <- %s", frame->hd.stream_id, buffer);
}
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* CURLVERBOSE */
if(!stream_id) {
/* stream ID zero is for connection-oriented stuff */
@@ -696,6 +516,10 @@
drain_tunnel(cf, data, &ctx->tunnel);
}
break;
+ case NGHTTP2_RST_STREAM:
+ if(frame->rst_stream.error_code)
+ ctx->tunnel.reset = TRUE;
+ break;
default:
break;
}
@@ -716,7 +540,6 @@
CURLcode result;
(void)flags;
- (void)data;
(void)session;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
if(stream_id != ctx->tunnel.stream_id) {
@@ -785,7 +608,6 @@
size_t nread;
(void)source;
- (void)data;
(void)ctx;
if(!stream_id)
@@ -849,7 +671,6 @@
struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)session;
- (void)data;
if(stream_id != ctx->tunnel.stream_id)
return 0;
@@ -858,6 +679,8 @@
stream_id, nghttp2_http2_strerror(error_code), error_code);
ctx->tunnel.closed = TRUE;
ctx->tunnel.error = error_code;
+ if(error_code)
+ ctx->tunnel.reset = TRUE;
return 0;
}
@@ -1055,6 +878,89 @@
return result;
}
+/*
+ * Initialize the cfilter context
+ */
+static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ nghttp2_session_callbacks *cbs = NULL;
+ int rc;
+
+ DEBUGASSERT(!ctx->h2);
+ memset(&ctx->tunnel, 0, sizeof(ctx->tunnel));
+
+ Curl_bufq_init(&ctx->inbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
+ Curl_bufq_init(&ctx->outbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
+
+ if(tunnel_stream_init(cf, &ctx->tunnel))
+ goto out;
+
+ rc = nghttp2_session_callbacks_new(&cbs);
+ if(rc) {
+ failf(data, "Could not initialize nghttp2 callbacks");
+ goto out;
+ }
+
+ nghttp2_session_callbacks_set_send_callback(cbs, on_session_send);
+ nghttp2_session_callbacks_set_on_frame_recv_callback(
+ cbs, proxy_h2_on_frame_recv);
+#ifdef CURLVERBOSE
+ nghttp2_session_callbacks_set_on_frame_send_callback(cbs,
+ proxy_h2_on_frame_send);
+#endif
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ cbs, tunnel_recv_callback);
+ nghttp2_session_callbacks_set_on_stream_close_callback(
+ cbs, proxy_h2_on_stream_close);
+ nghttp2_session_callbacks_set_on_header_callback(cbs, proxy_h2_on_header);
+
+ /* The nghttp2 session is not yet setup, do it */
+ rc = proxy_h2_client_new(cf, cbs);
+ if(rc) {
+ failf(data, "Could not initialize nghttp2");
+ goto out;
+ }
+
+ {
+ nghttp2_settings_entry iv[3];
+
+ iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
+ iv[0].value = Curl_multi_max_concurrent_streams(data->multi);
+ iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
+ iv[1].value = H2_TUNNEL_WINDOW_SIZE;
+ iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
+ iv[2].value = 0;
+ rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE, iv, 3);
+ if(rc) {
+ failf(data, "nghttp2_submit_settings() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+ }
+
+ rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0,
+ PROXY_HTTP2_HUGE_WINDOW_SIZE);
+ if(rc) {
+ failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+
+ /* all set, traffic will be send on connect */
+ result = CURLE_OK;
+
+out:
+ if(cbs)
+ nghttp2_session_callbacks_del(cbs);
+ CURL_TRC_CF(data, cf, "[0] init proxy ctx -> %d", result);
+ return result;
+}
+
static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
@@ -1086,7 +992,7 @@
}
DEBUGASSERT(ts->authority);
- if(Curl_timeleft_ms(data, TRUE) < 0) {
+ if(Curl_timeleft_ms(data) < 0) {
failf(data, "Proxy CONNECT aborted due to timeout");
result = CURLE_OPERATION_TIMEDOUT;
goto out;
@@ -1251,20 +1157,11 @@
struct cf_h2_proxy_ctx *ctx = cf->ctx;
*pnread = 0;
- if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) {
- CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
- "connection", ctx->tunnel.stream_id);
- failf(data, "proxy server refused HTTP/2 stream");
- return CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
- }
- else if(ctx->tunnel.error != NGHTTP2_NO_ERROR) {
- failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
- ctx->tunnel.stream_id, nghttp2_http2_strerror(ctx->tunnel.error),
- ctx->tunnel.error);
- return CURLE_HTTP2_STREAM;
- }
- else if(ctx->tunnel.reset) {
- failf(data, "HTTP/2 stream %u was reset", ctx->tunnel.stream_id);
+ if(ctx->tunnel.error) {
+ failf(data, "HTTP/2 stream %" PRIu32 " reset by %s (error 0x%" PRIx32
+ " %s)", ctx->tunnel.stream_id,
+ ctx->tunnel.reset ? "server" : "curl",
+ ctx->tunnel.error, nghttp2_http2_strerror(ctx->tunnel.error));
return CURLE_RECV_ERROR;
}
diff --git a/Utilities/cmcurl/lib/cf-haproxy.c b/Utilities/cmcurl/lib/cf-haproxy.c
index 6c9bfdd..782253e 100644
--- a/Utilities/cmcurl/lib/cf-haproxy.c
+++ b/Utilities/cmcurl/lib/cf-haproxy.c
@@ -156,7 +156,6 @@
static void cf_haproxy_destroy(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- (void)data;
CURL_TRC_CF(data, cf, "destroy");
cf_haproxy_ctx_free(cf->ctx);
}
diff --git a/Utilities/cmcurl/lib/cf-https-connect.c b/Utilities/cmcurl/lib/cf-https-connect.c
index d2a08d1..cabc6ab 100644
--- a/Utilities/cmcurl/lib/cf-https-connect.c
+++ b/Utilities/cmcurl/lib/cf-https-connect.c
@@ -30,6 +30,7 @@
#include "cfilters.h"
#include "connect.h"
#include "hostip.h"
+#include "httpsrr.h"
#include "multiif.h"
#include "cf-https-connect.h"
#include "http2.h"
@@ -221,6 +222,8 @@
/* install the winning filter below this one. */
cf->next = winner->cf;
winner->cf = NULL;
+ /* whatever errors where reported by ballers, clear our errorbuf */
+ Curl_reset_fail(data);
#ifdef USE_NGHTTP2
{
@@ -546,7 +549,6 @@
{
struct cf_hc_ctx *ctx = cf->ctx;
- (void)data;
CURL_TRC_CF(data, cf, "destroy");
cf_hc_reset(cf, data);
Curl_safefree(ctx);
diff --git a/Utilities/cmcurl/lib/cf-ip-happy.c b/Utilities/cmcurl/lib/cf-ip-happy.c
index 05e9505..dfbf4ae 100644
--- a/Utilities/cmcurl/lib/cf-ip-happy.c
+++ b/Utilities/cmcurl/lib/cf-ip-happy.c
@@ -50,6 +50,7 @@
#include "connect.h"
#include "cfilters.h"
#include "cf-ip-happy.h"
+#include "curl_addrinfo.h"
#include "curl_trc.h"
#include "multiif.h"
#include "progress.h"
@@ -227,7 +228,7 @@
struct Curl_easy *data,
bool *connected)
{
- *connected = a->connected;
+ *connected = (bool)a->connected;
if(!a->result && !*connected) {
/* evaluate again */
a->result = Curl_conn_cf_connect(a->cf, data, connected);
@@ -350,7 +351,8 @@
struct cf_ip_attempt *a = NULL, **panchor;
bool do_more;
timediff_t next_expire_ms;
- int i, inconclusive, ongoing;
+ int inconclusive, ongoing;
+ VERBOSE(int i);
if(bs->winner)
return CURLE_OK;
@@ -359,9 +361,9 @@
ongoing = inconclusive = 0;
/* check if a running baller connects now */
- i = -1;
+ VERBOSE(i = -1);
for(panchor = &bs->running; *panchor; panchor = &((*panchor)->next)) {
- ++i;
+ VERBOSE(++i);
a = *panchor;
a->result = cf_ip_attempt_connect(a, data, connected);
if(!a->result) {
@@ -425,6 +427,10 @@
addr = cf_ai_iter_next(&bs->addr_iter);
ai_family = bs->addr_iter.ai_family;
}
+ /* We are (re-)starting attempts. We are not interested in
+ * keeping old failure information. The new attempt will either
+ * succeed or persist new failure. */
+ Curl_reset_fail(data);
if(addr) { /* try another address */
result = cf_ip_attempt_new(&a, cf, data, addr, ai_family,
@@ -454,9 +460,9 @@
timediff_t delay_ms = bs->attempt_delay_ms - since_ms;
if(delay_ms <= 0) {
CURL_TRC_CF(data, cf, "all attempts inconclusive, restarting one");
- i = -1;
+ VERBOSE(i = -1);
for(a = bs->running; a; a = a->next) {
- ++i;
+ VERBOSE(++i);
if(!a->inconclusive)
continue;
result = cf_ip_attempt_restart(a, cf, data);
@@ -481,7 +487,7 @@
/* no more addresses, no inconclusive attempts */
CURL_TRC_CF(data, cf, "no more attempts to try");
result = CURLE_COULDNT_CONNECT;
- i = 0;
+ VERBOSE(i = 0);
for(a = bs->running; a; a = a->next) {
CURL_TRC_CF(data, cf, "baller %d: result=%d", i, a->result);
if(a->result)
@@ -495,11 +501,11 @@
bool more_possible;
/* when do we need to be called again? */
- next_expire_ms = Curl_timeleft_ms(data, TRUE);
- if(next_expire_ms <= 0) {
+ next_expire_ms = Curl_timeleft_ms(data);
+ if(next_expire_ms < 0) {
failf(data, "Connection timeout after %" FMT_OFF_T " ms",
- curlx_ptimediff_ms(Curl_pgrs_now(data),
- &data->progress.t_startsingle));
+ curlx_ptimediff_ms(Curl_pgrs_now(data),
+ &data->progress.t_startsingle));
return CURLE_OPERATION_TIMEDOUT;
}
@@ -698,7 +704,7 @@
if(!dns)
return CURLE_FAILED_INIT;
- if(Curl_timeleft_ms(data, TRUE) < 0) {
+ if(Curl_timeleft_ms(data) < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
@@ -791,10 +797,12 @@
ctx->ballers.winner->cf = NULL;
cf_ip_happy_ctx_clear(cf, data);
Curl_expire_done(data, EXPIRE_HAPPY_EYEBALLS);
+ /* whatever errors where reported by ballers, clear our errorbuf */
+ Curl_reset_fail(data);
- if(cf->conn->handler->protocol & PROTO_FAMILY_SSH)
+ if(cf->conn->scheme->protocol & PROTO_FAMILY_SSH)
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we are connected already */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
if(Curl_trc_cf_is_verbose(cf, data)) {
struct ip_quadruple ipquad;
bool is_ipv6;
diff --git a/Utilities/cmcurl/lib/cf-socket.c b/Utilities/cmcurl/lib/cf-socket.c
index ce728f5..2ebbe4d 100644
--- a/Utilities/cmcurl/lib/cf-socket.c
+++ b/Utilities/cmcurl/lib/cf-socket.c
@@ -55,12 +55,12 @@
#endif
#include "urldata.h"
-#include "bufq.h"
#include "curl_trc.h"
#include "if2ip.h"
#include "cfilters.h"
#include "cf-socket.h"
#include "connect.h"
+#include "curl_addrinfo.h"
#include "select.h"
#include "multiif.h"
#include "curlx/inet_pton.h"
@@ -68,7 +68,7 @@
#include "conncache.h"
#include "multihandle.h"
#include "rand.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#include "system_win32.h"
#include "curlx/nonblock.h"
#include "curlx/version_win32.h"
@@ -83,7 +83,7 @@
#if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED)
curl_socklen_t onoff = (curl_socklen_t)1;
int level = IPPROTO_TCP;
- char buffer[STRERROR_LEN];
+ VERBOSE(char buffer[STRERROR_LEN]);
if(setsockopt(sockfd, level, TCP_NODELAY,
(void *)&onoff, sizeof(onoff)) < 0)
@@ -96,42 +96,20 @@
#endif
}
-#ifdef SO_NOSIGPIPE
-/* The preferred method on macOS (10.2 and later) to prevent SIGPIPEs when
- sending data to a dead peer (instead of relying on the 4th argument to send
- being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
- systems? */
-static void nosigpipe(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t sockfd)
-{
- int onoff = 1;
- if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE,
- (void *)&onoff, sizeof(onoff)) < 0) {
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- char buffer[STRERROR_LEN];
- CURL_TRC_CF(data, cf, "Could not set SO_NOSIGPIPE: %s",
- curlx_strerror(SOCKERRNO, buffer, sizeof(buffer)));
-#else
- (void)cf;
- (void)data;
-#endif
- }
-}
-#else
-#define nosigpipe(x, y, z) Curl_nop_stmt
-#endif
-
+#if defined(USE_WINSOCK) || defined(TCP_KEEPIDLE) || \
+ defined(TCP_KEEPALIVE) || defined(TCP_KEEPALIVE_THRESHOLD) || \
+ defined(TCP_KEEPINTVL) || defined(TCP_KEEPALIVE_ABORT_THRESHOLD)
#if defined(USE_WINSOCK) || \
(defined(__sun) && !defined(TCP_KEEPIDLE)) || \
(defined(__DragonFly__) && __DragonFly_version < 500702) || \
(defined(_WIN32) && !defined(TCP_KEEPIDLE))
/* Solaris < 11.4, DragonFlyBSD < 500702 and Windows < 10.0.16299
* use millisecond units. */
-#define KEEPALIVE_FACTOR(x) (x *= 1000)
+#define KEEPALIVE_FACTOR(x) ((x) *= 1000)
#else
#define KEEPALIVE_FACTOR(x)
#endif
+#endif
static void tcpkeepalive(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -288,11 +266,11 @@
uint8_t transport)
{
/*
- * The Curl_sockaddr_ex structure is basically libcurl's external API
- * curl_sockaddr structure with enough space available to directly hold
- * any protocol-specific address structures. The variable declared here
- * will be used to pass / receive data to/from the fopensocket callback
- * if this has been set, before that, it is initialized from parameters.
+ * The Curl_sockaddr_ex structure is libcurl's external API curl_sockaddr
+ * structure with enough space available to directly hold any
+ * protocol-specific address structures. The variable declared here will be
+ * used to pass / receive data to/from the fopensocket callback if this has
+ * been set, before that, it is initialized from parameters.
*/
dest->family = ai->ai_family;
switch(transport) {
@@ -319,12 +297,25 @@
return CURLE_OK;
}
+#ifdef USE_SO_NOSIGPIPE
+int Curl_sock_nosigpipe(curl_socket_t sockfd)
+{
+ int onoff = 1;
+ return setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE,
+ (void *)&onoff, sizeof(onoff));
+}
+#endif /* USE_SO_NOSIGPIPE */
+
static CURLcode socket_open(struct Curl_easy *data,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
char errbuf[STRERROR_LEN];
+#ifdef SOCK_CLOEXEC
+ addr->socktype |= SOCK_CLOEXEC;
+#endif
+
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
if(data->set.fopensocket) {
@@ -344,7 +335,13 @@
Curl_set_in_callback(data, FALSE);
}
else {
- /* opensocket callback not set, so simply create the socket now */
+ /* opensocket callback not set, so create the socket now */
+#ifdef DEBUGBUILD
+ if((addr->family == AF_INET6) && getenv("CURL_DBG_SOCK_FAIL_IPV6")) {
+ failf(data, "CURL_DBG_SOCK_FAIL_IPV6: failed to open socket");
+ return CURLE_COULDNT_CONNECT;
+ }
+#endif
*sockfd = CURL_SOCKET(addr->family, addr->socktype, addr->protocol);
if((*sockfd == CURL_SOCKET_BAD) && (SOCKERRNO == SOCKENOMEM))
return CURLE_OUT_OF_MEMORY;
@@ -357,11 +354,21 @@
return CURLE_COULDNT_CONNECT;
}
-#ifdef HAVE_FCNTL
+#ifdef USE_SO_NOSIGPIPE
+ if(Curl_sock_nosigpipe(*sockfd) < 0) {
+ failf(data, "setsockopt enable SO_NOSIGPIPE: %s",
+ curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf)));
+ sclose(*sockfd);
+ *sockfd = CURL_SOCKET_BAD;
+ return CURLE_COULDNT_CONNECT;
+ }
+#endif /* USE_SO_NOSIGPIPE */
+
+#if defined(HAVE_FCNTL) && !defined(SOCK_CLOEXEC)
if(fcntl(*sockfd, F_SETFD, FD_CLOEXEC) < 0) {
failf(data, "fcntl set CLOEXEC: %s",
curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf)));
- close(*sockfd);
+ sclose(*sockfd);
*sockfd = CURL_SOCKET_BAD;
return CURLE_COULDNT_CONNECT;
}
@@ -408,7 +415,7 @@
static int socket_close(struct Curl_easy *data, struct connectdata *conn,
int use_callback, curl_socket_t sock)
{
- if(CURL_SOCKET_BAD == sock)
+ if(sock == CURL_SOCKET_BAD)
return 0;
if(use_callback && conn && conn->fclosesocket) {
@@ -440,37 +447,6 @@
return socket_close(data, conn, FALSE, sock);
}
-#ifdef USE_WINSOCK
-/* When you run a program that uses the Windows Sockets API, you may
- experience slow performance when you copy data to a TCP server.
-
- https://learn.microsoft.com/troubleshoot/windows-server/networking/slow-performance-copy-data-tcp-server-sockets-api
-
- Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
- Buffer Size
-
- The problem described in this knowledge-base is applied only to pre-Vista
- Windows. Following function trying to detect OS version and skips
- SO_SNDBUF adjustment for Windows Vista and above.
-*/
-
-void Curl_sndbuf_init(curl_socket_t sockfd)
-{
- int val = CURL_MAX_WRITE_SIZE + 32;
- int curval = 0;
- int curlen = sizeof(curval);
-
- if(Curl_isVistaOrGreater)
- return;
-
- if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
- if(curval > val)
- return;
-
- setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
-}
-#endif /* USE_WINSOCK */
-
/*
* Curl_parse_interface()
*
@@ -516,14 +492,14 @@
input += strlen(if_prefix);
if(!*input)
return CURLE_BAD_FUNCTION_ARGUMENT;
- *iface = Curl_memdup0(input, len - strlen(if_prefix));
+ *iface = curlx_memdup0(input, len - strlen(if_prefix));
return *iface ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
else if(!strncmp(host_prefix, input, strlen(host_prefix))) {
input += strlen(host_prefix);
if(!*input)
return CURLE_BAD_FUNCTION_ARGUMENT;
- *host = Curl_memdup0(input, len - strlen(host_prefix));
+ *host = curlx_memdup0(input, len - strlen(host_prefix));
return *host ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
else if(!strncmp(if_host_prefix, input, strlen(if_host_prefix))) {
@@ -533,11 +509,11 @@
host_part = memchr(input, '!', len);
if(!host_part || !*(host_part + 1))
return CURLE_BAD_FUNCTION_ARGUMENT;
- *iface = Curl_memdup0(input, host_part - input);
+ *iface = curlx_memdup0(input, host_part - input);
if(!*iface)
return CURLE_OUT_OF_MEMORY;
++host_part;
- *host = Curl_memdup0(host_part, len - (host_part - input));
+ *host = curlx_memdup0(host_part, len - (host_part - input));
if(!*host) {
curlx_free(*iface);
*iface = NULL;
@@ -548,7 +524,7 @@
if(!*input)
return CURLE_BAD_FUNCTION_ARGUMENT;
- *dev = Curl_memdup0(input, len);
+ *dev = curlx_memdup0(input, len);
return *dev ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
@@ -604,10 +580,10 @@
* This binds the local socket to a particular interface. This will
* force even requests to other local interfaces to go out the external
* interface. Only bind to the interface when specified as interface,
- * not just as a hostname or ip address.
+ * not as a hostname or ip address.
*
* The interface might be a VRF, eg: vrf-blue, which means it cannot be
- * converted to an IP address and would fail Curl_if2ip. Simply try to
+ * converted to an IP address and would fail Curl_if2ip. Try to
* use it straight away.
*/
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
@@ -822,7 +798,7 @@
*
* "I do not have Rational Quantify, but the hint from his post was
* ntdll::NtRemoveIoCompletion(). I would assume the SleepEx (or maybe
- * just Sleep(0) would be enough?) would release whatever
+ * Sleep(0) would be enough?) would release whatever
* mutex/critical-section the ntdll call is waiting on.
*
* Someone got to verify this on Win-NT 4.0, 2000."
@@ -877,15 +853,12 @@
default:
/* unknown error, fallthrough and try another address! */
-#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)ipaddress;
-#else
{
- char buffer[STRERROR_LEN];
+ VERBOSE(char buffer[STRERROR_LEN]);
infof(data, "Immediate connect fail for %s: %s", ipaddress,
curlx_strerror(error, buffer, sizeof(buffer)));
+ NOVERBOSE((void)ipaddress);
}
-#endif
data->state.os_errno = error;
/* connect failed */
return CURLE_COULDNT_CONNECT;
@@ -968,7 +941,7 @@
{
struct cf_socket_ctx *ctx = cf->ctx;
- if(ctx && CURL_SOCKET_BAD != ctx->sock) {
+ if(ctx && ctx->sock != CURL_SOCKET_BAD) {
CURL_TRC_CF(data, cf, "cf_socket_close, fd=%" FMT_SOCKET_T, ctx->sock);
if(ctx->sock == cf->conn->sock[cf->sockindex])
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
@@ -1023,16 +996,15 @@
#ifdef HAVE_GETSOCKNAME
if((ctx->sock != CURL_SOCKET_BAD) &&
- !(data->conn->handler->protocol & CURLPROTO_TFTP)) {
+ !(data->conn->scheme->protocol & CURLPROTO_TFTP)) {
/* TFTP does not connect, so it cannot get the IP like this */
-
- char buffer[STRERROR_LEN];
struct Curl_sockaddr_storage ssloc;
curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage);
+ VERBOSE(char buffer[STRERROR_LEN]);
memset(&ssloc, 0, sizeof(ssloc));
if(getsockname(ctx->sock, (struct sockaddr *)&ssloc, &slen)) {
- int error = SOCKERRNO;
+ VERBOSE(int error = SOCKERRNO);
infof(data, "getsockname() failed with errno %d: %s",
error, curlx_strerror(error, buffer, sizeof(buffer)));
}
@@ -1068,6 +1040,19 @@
return CURLE_OK;
}
+/* to figure out the type of the socket safely, remove the possibly ORed
+ bits before comparing */
+static int cf_socktype(int x)
+{
+#ifdef SOCK_CLOEXEC
+ x &= ~SOCK_CLOEXEC;
+#endif
+#ifdef SOCK_NONBLOCK
+ x &= ~SOCK_NONBLOCK;
+#endif
+ return x;
+}
+
static CURLcode cf_socket_open(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@@ -1077,7 +1062,6 @@
CURLcode result = CURLE_COULDNT_CONNECT;
bool is_tcp;
- (void)data;
DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
ctx->started_at = *Curl_pgrs_now(data);
#ifdef SOCK_NONBLOCK
@@ -1124,18 +1108,14 @@
#ifdef USE_IPV6
is_tcp = (ctx->addr.family == AF_INET ||
ctx->addr.family == AF_INET6) &&
- ctx->addr.socktype == SOCK_STREAM;
+ cf_socktype(ctx->addr.socktype) == SOCK_STREAM;
#else
is_tcp = (ctx->addr.family == AF_INET) &&
- ctx->addr.socktype == SOCK_STREAM;
+ cf_socktype(ctx->addr.socktype) == SOCK_STREAM;
#endif
if(is_tcp && data->set.tcp_nodelay)
tcpnodelay(cf, data, ctx->sock);
- nosigpipe(cf, data, ctx->sock);
-
- Curl_sndbuf_init(ctx->sock);
-
if(is_tcp && data->set.tcp_keepalive)
tcpkeepalive(cf, data, ctx->sock);
@@ -1196,7 +1176,7 @@
}
}
#endif
- ctx->sock_connected = (ctx->addr.socktype != SOCK_DGRAM);
+ ctx->sock_connected = (cf_socktype(ctx->addr.socktype) != SOCK_DGRAM);
out:
if(result) {
if(ctx->sock != CURL_SOCKET_BAD) {
@@ -1277,7 +1257,6 @@
CURLcode result = CURLE_COULDNT_CONNECT;
int rc = 0;
- (void)data;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
@@ -1297,12 +1276,12 @@
}
/* Connect TCP socket */
- rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen);
+ rc = do_connect(cf, data, (bool)cf->conn->bits.tcp_fastopen);
error = SOCKERRNO;
set_local_ip(cf, data);
CURL_TRC_CF(data, cf, "local address %s port %d...",
ctx->ip.local_ip, ctx->ip.local_port);
- if(-1 == rc) {
+ if(rc == -1) {
result = socket_connect_result(data, ctx->ip.remote_ip, error);
goto out;
}
@@ -1341,18 +1320,14 @@
out:
if(result) {
if(ctx->error) {
+ VERBOSE(char buffer[STRERROR_LEN]);
set_local_ip(cf, data);
data->state.os_errno = ctx->error;
SET_SOCKERRNO(ctx->error);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- {
- char buffer[STRERROR_LEN];
- infof(data, "connect to %s port %u from %s port %d failed: %s",
- ctx->ip.remote_ip, ctx->ip.remote_port,
- ctx->ip.local_ip, ctx->ip.local_port,
- curlx_strerror(ctx->error, buffer, sizeof(buffer)));
- }
-#endif
+ infof(data, "connect to %s port %u from %s port %d failed: %s",
+ ctx->ip.remote_ip, ctx->ip.remote_port,
+ ctx->ip.local_ip, ctx->ip.local_port,
+ curlx_strerror(ctx->error, buffer, sizeof(buffer)));
}
if(ctx->sock != CURL_SOCKET_BAD) {
socket_close(data, cf->conn, TRUE, ctx->sock);
@@ -1429,8 +1404,8 @@
struct cf_socket_ctx *ctx = cf->ctx;
curl_socket_t fdsave;
ssize_t rv;
- size_t orig_len = len;
CURLcode result = CURLE_OK;
+ VERBOSE(size_t orig_len = len);
(void)eos;
*pnwritten = 0;
@@ -1483,7 +1458,7 @@
(SOCKEINPROGRESS == sockerr)
#endif
) {
- /* this is just a case of EWOULDBLOCK */
+ /* EWOULDBLOCK */
result = CURLE_AGAIN;
}
else {
@@ -1525,10 +1500,9 @@
}
}
if(cf->cft != &Curl_cft_udp && ctx->recv_max && ctx->recv_max < len) {
- size_t orig_len = len;
- len = ctx->recv_max;
CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE max read of %zu bytes",
- orig_len, len);
+ len, ctx->recv_max);
+ len = ctx->recv_max;
}
#endif
@@ -1549,7 +1523,7 @@
(EAGAIN == sockerr) || (SOCKEINTR == sockerr)
#endif
) {
- /* this is just a case of EWOULDBLOCK */
+ /* EWOULDBLOCK */
result = CURLE_AGAIN;
}
else {
@@ -1627,7 +1601,7 @@
int r;
*input_pending = FALSE;
- (void)data;
+
if(!ctx || ctx->sock == CURL_SOCKET_BAD)
return FALSE;
@@ -1827,7 +1801,7 @@
NOLINTNEXTLINE(clang-analyzer-unix.StdCLibraryFunctions) */
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,
(curl_socklen_t)ctx->addr.addrlen);
- if(-1 == rc) {
+ if(rc == -1) {
return socket_connect_result(data, ctx->ip.remote_ip, SOCKERRNO);
}
ctx->sock_connected = TRUE;
@@ -2004,7 +1978,7 @@
#endif
/* check if the generic timeout possibly is set shorter */
- other_ms = Curl_timeleft_ms(data, FALSE);
+ other_ms = Curl_timeleft_ms(data);
if(other_ms && (other_ms < timeout_ms))
/* note that this also works fine for when other_ms happens to be negative
due to it already having elapsed */
@@ -2113,7 +2087,7 @@
s_accepted = CURL_ACCEPT(ctx->sock, (struct sockaddr *)&add, &size);
#endif
- if(CURL_SOCKET_BAD == s_accepted) {
+ if(s_accepted == CURL_SOCKET_BAD) {
failf(data, "Error accept()ing server connect: %s",
curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf)));
return CURLE_FTP_ACCEPT_FAILED;
diff --git a/Utilities/cmcurl/lib/cf-socket.h b/Utilities/cmcurl/lib/cf-socket.h
index 9db492e..014f5f7 100644
--- a/Utilities/cmcurl/lib/cf-socket.h
+++ b/Utilities/cmcurl/lib/cf-socket.h
@@ -35,8 +35,8 @@
struct ip_quadruple;
/*
- * The Curl_sockaddr_ex structure is basically libcurl's external API
- * curl_sockaddr structure with enough space available to directly hold any
+ * The Curl_sockaddr_ex structure is libcurl's external API curl_sockaddr
+ * structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
* used to pass / receive data to/from the fopensocket callback if this has
* been set, before that, it is initialized from parameters.
@@ -73,24 +73,14 @@
uint8_t transport,
curl_socket_t *sockfd);
+#ifdef USE_SO_NOSIGPIPE
+/* Set SO_NOSIGPIPE on socket, return < 0 on error. */
+int Curl_sock_nosigpipe(curl_socket_t sockfd);
+#endif
+
int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sock);
-#ifdef USE_WINSOCK
-/* When you run a program that uses the Windows Sockets API, you may
- experience slow performance when you copy data to a TCP server.
-
- https://learn.microsoft.com/troubleshoot/windows-server/networking/slow-performance-copy-data-tcp-server-sockets-api
-
- Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
- Buffer Size
-
-*/
-void Curl_sndbuf_init(curl_socket_t sockfd);
-#else
-#define Curl_sndbuf_init(y) Curl_nop_stmt
-#endif
-
/**
* Creates a cfilter that opens a TCP socket to the given address
* when calling its `connect` implementation.
diff --git a/Utilities/cmcurl/lib/cfilters.c b/Utilities/cmcurl/lib/cfilters.c
index b91d30c..27b0306 100644
--- a/Utilities/cmcurl/lib/cfilters.c
+++ b/Utilities/cmcurl/lib/cfilters.c
@@ -33,9 +33,6 @@
#include "select.h"
#include "curlx/strparse.h"
-static void cf_cntrl_update_info(struct Curl_easy *data,
- struct connectdata *conn);
-
#ifdef UNITTESTS
/* used by unit2600.c */
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -55,9 +52,6 @@
return CURLE_OK;
}
-static void conn_report_connect_stats(struct Curl_cfilter *cf,
- struct Curl_easy *data);
-
CURLcode Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
@@ -142,22 +136,22 @@
}
void Curl_conn_cf_discard_all(struct Curl_easy *data,
- struct connectdata *conn, int index)
+ struct connectdata *conn, int sockindex)
{
- Curl_conn_cf_discard_chain(&conn->cfilter[index], data);
+ Curl_conn_cf_discard_chain(&conn->cfilter[sockindex], data);
}
-void Curl_conn_close(struct Curl_easy *data, int index)
+void Curl_conn_close(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
/* it is valid to call that without filters being present */
- cf = data->conn->cfilter[index];
+ cf = data->conn->cfilter[sockindex];
if(cf) {
cf->cft->do_close(cf, data);
}
- Curl_shutdown_clear(data, index);
+ Curl_shutdown_clear(data, sockindex);
}
CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done)
@@ -183,8 +177,6 @@
*done = FALSE;
if(!Curl_shutdown_started(data, sockindex)) {
- CURL_TRC_M(data, "shutdown start on%s connection",
- sockindex ? " secondary" : "");
Curl_shutdown_start(data, sockindex, 0);
}
else {
@@ -217,14 +209,14 @@
return result;
}
-CURLcode Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
+CURLcode Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, size_t *pnread)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- cf = data->conn->cfilter[num];
+ cf = data->conn->cfilter[sockindex];
while(cf && !cf->connected)
cf = cf->next;
if(cf)
@@ -235,19 +227,19 @@
return CURLE_FAILED_INIT;
}
-CURLcode Curl_cf_send(struct Curl_easy *data, int num,
- const uint8_t *mem, size_t len, bool eos,
+CURLcode Curl_cf_send(struct Curl_easy *data, int sockindex,
+ const uint8_t *buf, size_t len, bool eos,
size_t *pnwritten)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- cf = data->conn->cfilter[num];
+ cf = data->conn->cfilter[sockindex];
while(cf && !cf->connected)
cf = cf->next;
if(cf) {
- return cf->cft->do_send(cf, data, mem, len, eos, pnwritten);
+ return cf->cft->do_send(cf, data, buf, len, eos, pnwritten);
}
failf(data, "send: no filter connected");
DEBUGASSERT(0);
@@ -336,18 +328,17 @@
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
- int index,
+ int sockindex,
struct Curl_cfilter *cf)
{
- (void)data;
DEBUGASSERT(conn);
DEBUGASSERT(!cf->conn);
DEBUGASSERT(!cf->next);
- cf->next = conn->cfilter[index];
+ cf->next = conn->cfilter[sockindex];
cf->conn = conn;
- cf->sockindex = index;
- conn->cfilter[index] = cf;
+ cf->sockindex = sockindex;
+ conn->cfilter[sockindex] = cf;
CURL_TRC_CF(data, cf, "added");
}
@@ -429,7 +420,7 @@
return CURLE_RECV_ERROR;
}
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
static CURLcode cf_verboseconnect(struct Curl_easy *data,
struct Curl_cfilter *cf)
{
@@ -452,6 +443,51 @@
}
#endif
+static CURLcode cf_cntrl_all(struct connectdata *conn,
+ struct Curl_easy *data,
+ bool ignore_result,
+ int event, int arg1, void *arg2)
+{
+ CURLcode result = CURLE_OK;
+ size_t i;
+
+ for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
+ result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
+ event, arg1, arg2);
+ if(!ignore_result && result)
+ break;
+ }
+ return result;
+}
+
+static void cf_cntrl_update_info(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
+}
+
+/**
+ * Update connection statistics
+ */
+static void conn_report_connect_stats(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ if(cf) {
+ struct curltime connected;
+ struct curltime appconnected;
+
+ memset(&connected, 0, sizeof(connected));
+ cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
+ if(connected.tv_sec || connected.tv_usec)
+ Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
+
+ memset(&appconnected, 0, sizeof(appconnected));
+ cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
+ if(appconnected.tv_sec || appconnected.tv_usec)
+ Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
+ }
+}
+
CURLcode Curl_conn_connect(struct Curl_easy *data,
int sockindex,
bool blocking,
@@ -475,7 +511,7 @@
return CURLE_FAILED_INIT;
}
- *done = cf->connected;
+ *done = (bool)cf->connected;
if(*done)
return CURLE_OK;
@@ -499,9 +535,7 @@
cf_cntrl_update_info(data, data->conn);
conn_report_connect_stats(cf, data);
data->conn->keepalive = *Curl_pgrs_now(data);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- result = cf_verboseconnect(data, cf);
-#endif
+ VERBOSE(result = cf_verboseconnect(data, cf));
goto out;
}
else if(result) {
@@ -514,7 +548,7 @@
goto out;
else {
/* check allowed time left */
- const timediff_t timeout_ms = Curl_timeleft_ms(data, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft_ms(data);
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int rc;
@@ -572,8 +606,8 @@
return FALSE;
cf = conn->cfilter[sockindex];
if(cf)
- return cf->connected;
- else if(conn->handler->flags & PROTOPT_NONETWORK)
+ return (bool)cf->connected;
+ else if(conn->scheme->flags & PROTOPT_NONETWORK)
return TRUE;
return FALSE;
}
@@ -837,7 +871,7 @@
CURLcode result = CURLE_OK;
for(; cf; cf = cf->next) {
- if(Curl_cf_def_cntrl == cf->cft->cntrl)
+ if(cf->cft->cntrl == Curl_cf_def_cntrl)
continue;
result = cf->cft->cntrl(cf, data, event, arg1, arg2);
if(!ignore_result && result)
@@ -923,23 +957,6 @@
return cf ? cf_get_remote_addr(cf, data) : NULL;
}
-static CURLcode cf_cntrl_all(struct connectdata *conn,
- struct Curl_easy *data,
- bool ignore_result,
- int event, int arg1, void *arg2)
-{
- CURLcode result = CURLE_OK;
- size_t i;
-
- for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
- result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
- event, arg1, arg2);
- if(!ignore_result && result)
- break;
- }
- return result;
-}
-
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE, CF_CTRL_DATA_SETUP, 0, NULL);
@@ -977,34 +994,6 @@
CF_CTRL_DATA_PAUSE, do_pause, NULL);
}
-static void cf_cntrl_update_info(struct Curl_easy *data,
- struct connectdata *conn)
-{
- cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
-}
-
-/**
- * Update connection statistics
- */
-static void conn_report_connect_stats(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- if(cf) {
- struct curltime connected;
- struct curltime appconnected;
-
- memset(&connected, 0, sizeof(connected));
- cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
- if(connected.tv_sec || connected.tv_usec)
- Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
-
- memset(&appconnected, 0, sizeof(appconnected));
- cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
- if(appconnected.tv_sec || appconnected.tv_usec)
- Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
- }
-}
-
bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
bool *input_pending)
{
@@ -1071,23 +1060,23 @@
}
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
- char *buf, size_t blen, size_t *pnread)
+ char *buf, size_t len, size_t *pnread)
{
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
if(!CONN_SOCK_IDX_VALID(sockindex))
return CURLE_BAD_FUNCTION_ARGUMENT;
if(data && data->conn && data->conn->recv[sockindex])
- return data->conn->recv[sockindex](data, sockindex, buf, blen, pnread);
+ return data->conn->recv[sockindex](data, sockindex, buf, len, pnread);
*pnread = 0;
return CURLE_FAILED_INIT;
}
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
- const void *buf, size_t blen, bool eos,
+ const void *buf, size_t len, bool eos,
size_t *pnwritten)
{
- size_t write_len = blen;
+ size_t write_len = len;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
@@ -1100,13 +1089,14 @@
const char *p = getenv("CURL_SMALLSENDS");
if(p) {
curl_off_t altsize;
- if(!curlx_str_number(&p, &altsize, write_len))
+ if(!curlx_str_number(&p, &altsize, write_len)) {
write_len = (size_t)altsize;
+ if(write_len != len)
+ eos = FALSE;
+ }
}
}
#endif
- if(write_len != blen)
- eos = FALSE;
if(data && data->conn && data->conn->send[sockindex])
return data->conn->send[sockindex](data, sockindex, buf, write_len, eos,
pnwritten);
diff --git a/Utilities/cmcurl/lib/cfilters.h b/Utilities/cmcurl/lib/cfilters.h
index 9faf01d..c754634 100644
--- a/Utilities/cmcurl/lib/cfilters.h
+++ b/Utilities/cmcurl/lib/cfilters.h
@@ -117,7 +117,7 @@
*/
/* data event arg1 arg2 return */
#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
-/* unused now 5 */
+/* unused now 5 */
#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */
#define CF_CTRL_DATA_DONE 7 /* premature NULL ignored */
#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
@@ -170,7 +170,7 @@
#define CF_QUERY_STREAM_ERROR 6 /* error code - */
#define CF_QUERY_NEED_FLUSH 7 /* TRUE/FALSE - */
#define CF_QUERY_IP_INFO 8 /* TRUE/FALSE struct ip_quadruple */
-#define CF_QUERY_HTTP_VERSION 9 /* number (10/11/20/30) - */
+#define CF_QUERY_HTTP_VERSION 9 /* number (10/11/20/30) - */
/* pass in a `const struct Curl_sockaddr_ex **` as `pres2`. Gets set
* to NULL when not connected. */
#define CF_QUERY_REMOTE_ADDR 10 /* - `Curl_sockaddr_ex *` */
@@ -312,8 +312,7 @@
* Remove and destroy all filters at chain `sockindex` on connection `conn`.
*/
void Curl_conn_cf_discard_all(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex);
+ struct connectdata *conn, int sockindex);
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -349,7 +348,7 @@
const char *Curl_conn_cf_get_alpn_negotiated(struct Curl_cfilter *cf,
struct Curl_easy *data);
-#define CURL_CF_SSL_DEFAULT -1
+#define CURL_CF_SSL_DEFAULT (-1)
#define CURL_CF_SSL_DISABLE 0
#define CURL_CF_SSL_ENABLE 1
@@ -608,15 +607,14 @@
* Will return CURLE_AGAIN iff blocked on receiving.
*/
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
- char *buf, size_t buffersize,
- size_t *pnread);
+ char *buf, size_t len, size_t *pnread);
/*
* Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
* Will return CURLE_AGAIN iff blocked on sending.
*/
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
- const void *buf, size_t blen, bool eos,
+ const void *buf, size_t len, bool eos,
size_t *pnwritten);
/**
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 1a3dba7..a865959 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -34,9 +34,6 @@
#include "conncache.h"
#include "curl_share.h"
#include "sigpipe.h"
-#include "connect.h"
-#include "select.h"
-#include "curlx/strparse.h"
#define CPOOL_IS_LOCKED(c) ((c) && (c)->locked)
@@ -52,7 +49,7 @@
} \
} while(0)
-#define CPOOL_UNLOCK(c,d) \
+#define CPOOL_UNLOCK(c, d) \
do { \
if(c) { \
DEBUGASSERT((c)->locked); \
@@ -69,11 +66,6 @@
char dest[1]; /* destination of bundle, allocated to keep dest_len bytes */
};
-static void cpool_discard_conn(struct cpool *cpool,
- struct Curl_easy *data,
- struct connectdata *conn,
- bool aborted);
-
static struct cpool_bundle *cpool_bundle_create(const char *dest)
{
struct cpool_bundle *bundle;
@@ -189,26 +181,74 @@
}
}
+static void cpool_discard_conn(struct cpool *cpool,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ bool aborted)
+{
+ bool done = FALSE;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(!data->conn);
+ DEBUGASSERT(cpool);
+ DEBUGASSERT(!conn->bits.in_cpool);
+
+ /*
+ * If this connection is not marked to force-close, leave it open if there
+ * are other users of it
+ */
+ if(CONN_INUSE(conn) && !aborted) {
+ CURL_TRC_M(data, "[CPOOL] not discarding #%" FMT_OFF_T
+ " still in use by %u transfers", conn->connection_id,
+ conn->attached_xfers);
+ return;
+ }
+
+ /* treat the connection as aborted in CONNECT_ONLY situations, we do
+ * not know what the APP did with it. */
+ if(conn->connect_only)
+ aborted = TRUE;
+ conn->bits.aborted = aborted;
+
+ /* We do not shutdown dead connections. The term 'dead' can be misleading
+ * here, as we also mark errored connections/transfers as 'dead'.
+ * If we do a shutdown for an aborted transfer, the server might think
+ * it was successful otherwise (for example an ftps: upload). This is
+ * not what we want. */
+ if(aborted)
+ done = TRUE;
+ if(!done) {
+ /* Attempt to shutdown the connection right away. */
+ Curl_cshutdn_run_once(cpool->idata, conn, &done);
+ }
+
+ if(done || !data->multi)
+ Curl_cshutdn_terminate(cpool->idata, conn, FALSE);
+ else
+ Curl_cshutdn_add(&data->multi->cshutdn, conn, cpool->num_conn);
+}
+
void Curl_cpool_destroy(struct cpool *cpool)
{
if(cpool && cpool->initialised && cpool->idata) {
struct connectdata *conn;
- SIGPIPE_VARIABLE(pipe_st);
+ struct Curl_sigpipe_ctx pipe_ctx;
CURL_TRC_M(cpool->idata, "%s[CPOOL] destroy, %zu connections",
cpool->share ? "[SHARE] " : "", cpool->num_conn);
/* Move all connections to the shutdown list */
- sigpipe_init(&pipe_st);
+ sigpipe_init(&pipe_ctx);
CPOOL_LOCK(cpool, cpool->idata);
conn = cpool_get_first(cpool);
+ if(conn)
+ sigpipe_apply(cpool->idata, &pipe_ctx);
while(conn) {
cpool_remove_conn(cpool, conn);
- sigpipe_apply(cpool->idata, &pipe_st);
cpool_discard_conn(cpool, cpool->idata, conn, FALSE);
conn = cpool_get_first(cpool);
}
CPOOL_UNLOCK(cpool, cpool->idata);
- sigpipe_restore(&pipe_st);
+ sigpipe_restore(&pipe_ctx);
Curl_hash_destroy(&cpool->dest2bundle);
}
}
@@ -592,53 +632,6 @@
return result;
}
-static void cpool_discard_conn(struct cpool *cpool,
- struct Curl_easy *data,
- struct connectdata *conn,
- bool aborted)
-{
- bool done = FALSE;
-
- DEBUGASSERT(data);
- DEBUGASSERT(!data->conn);
- DEBUGASSERT(cpool);
- DEBUGASSERT(!conn->bits.in_cpool);
-
- /*
- * If this connection is not marked to force-close, leave it open if there
- * are other users of it
- */
- if(CONN_INUSE(conn) && !aborted) {
- CURL_TRC_M(data, "[CPOOL] not discarding #%" FMT_OFF_T
- " still in use by %u transfers", conn->connection_id,
- conn->attached_xfers);
- return;
- }
-
- /* treat the connection as aborted in CONNECT_ONLY situations, we do
- * not know what the APP did with it. */
- if(conn->connect_only)
- aborted = TRUE;
- conn->bits.aborted = aborted;
-
- /* We do not shutdown dead connections. The term 'dead' can be misleading
- * here, as we also mark errored connections/transfers as 'dead'.
- * If we do a shutdown for an aborted transfer, the server might think
- * it was successful otherwise (for example an ftps: upload). This is
- * not what we want. */
- if(aborted)
- done = TRUE;
- if(!done) {
- /* Attempt to shutdown the connection right away. */
- Curl_cshutdn_run_once(cpool->idata, conn, &done);
- }
-
- if(done || !data->multi)
- Curl_cshutdn_terminate(cpool->idata, conn, FALSE);
- else
- Curl_cshutdn_add(&data->multi->cshutdn, conn, cpool->num_conn);
-}
-
void Curl_conn_terminate(struct Curl_easy *data,
struct connectdata *conn,
bool aborted)
@@ -808,7 +801,7 @@
struct connectdata *conn, void *param)
{
struct cpool_do_conn_ctx *dctx = param;
- (void)data;
+
if(conn->connection_id == dctx->id) {
dctx->cb(conn, data, dctx->cbdata);
return 1;
@@ -858,7 +851,6 @@
static int cpool_reap_no_reuse(struct Curl_easy *data,
struct connectdata *conn, void *param)
{
- (void)data;
(void)param;
if(!CONN_INUSE(conn) && conn->bits.no_reuse) {
Curl_conn_terminate(data, conn, FALSE);
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index 9b392af..d8626ae 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -68,7 +68,7 @@
size_t size);
/* Destroy all connections and free all members */
-void Curl_cpool_destroy(struct cpool *connc);
+void Curl_cpool_destroy(struct cpool *cpool);
/* Init the transfer to be used within its connection pool.
* Assigns `data->id`. */
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 6e17834..78c9370 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -61,7 +61,7 @@
#include "multiif.h"
#include "curlx/inet_ntop.h"
#include "curlx/strparse.h"
-#include "vtls/vtls.h" /* for vtsl cfilters */
+#include "vtls/vtls.h" /* for vtls cfilters */
#include "progress.h"
#include "conncache.h"
#include "multihandle.h"
@@ -100,25 +100,27 @@
* transfer/connection. If the value is 0, there is no timeout (ie there is
* infinite time left). If the value is negative, the timeout time has already
* elapsed.
- * @param data the transfer to check on
- * @param duringconnect TRUE iff connect timeout is also taken into account.
* @unittest: 1303
*/
timediff_t Curl_timeleft_now_ms(struct Curl_easy *data,
- const struct curltime *pnow,
- bool duringconnect)
+ const struct curltime *pnow)
{
timediff_t timeleft_ms = 0;
timediff_t ctimeleft_ms = 0;
- timediff_t ctimeout_ms;
- /* The duration of a connect and the total transfer are calculated from two
- different time-stamps. It can end up with the total timeout being reached
- before the connect timeout expires and we must acknowledge whichever
- timeout that is reached first. The total timeout is set per entire
- operation, while the connect timeout is set per connect. */
- if((!data->set.timeout || data->set.connect_only) && !duringconnect)
+ if(Curl_shutdown_started(data, FIRSTSOCKET))
+ return Curl_shutdown_timeleft(data, data->conn, FIRSTSOCKET);
+ else if(Curl_is_connecting(data)) {
+ timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ?
+ data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
+ ctimeleft_ms = ctimeout_ms -
+ curlx_ptimediff_ms(pnow, &data->progress.t_startsingle);
+ if(!ctimeleft_ms)
+ ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
+ }
+ else if(!data->set.timeout || data->set.connect_only) {
return 0; /* no timeout in place or checked, return "no limit" */
+ }
if(data->set.timeout) {
timeleft_ms = data->set.timeout -
@@ -127,25 +129,16 @@
timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
}
- if(!duringconnect)
- return timeleft_ms; /* no connect check, this is it */
- ctimeout_ms = (data->set.connecttimeout > 0) ?
- data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
- ctimeleft_ms = ctimeout_ms -
- curlx_ptimediff_ms(pnow, &data->progress.t_startsingle);
if(!ctimeleft_ms)
- ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
- if(!timeleft_ms)
- return ctimeleft_ms; /* no general timeout, this is it */
-
- /* return minimal time left or max amount already expired */
- return (ctimeleft_ms < timeleft_ms) ? ctimeleft_ms : timeleft_ms;
+ return timeleft_ms;
+ else if(!timeleft_ms)
+ return ctimeleft_ms;
+ return CURLMIN(ctimeleft_ms, timeleft_ms);
}
-timediff_t Curl_timeleft_ms(struct Curl_easy *data,
- bool duringconnect)
+timediff_t Curl_timeleft_ms(struct Curl_easy *data)
{
- return Curl_timeleft_now_ms(data, Curl_pgrs_now(data), duringconnect);
+ return Curl_timeleft_now_ms(data, Curl_pgrs_now(data));
}
void Curl_shutdown_start(struct Curl_easy *data, int sockindex,
@@ -162,6 +155,8 @@
/* Set a timer, unless we operate on the admin handle */
if(data->mid)
Curl_expire_ex(data, conn->shutdown.timeout_ms, EXPIRE_SHUTDOWN);
+ CURL_TRC_M(data, "shutdown start on%s connection",
+ sockindex ? " secondary" : "");
}
timediff_t Curl_shutdown_timeleft(struct Curl_easy *data,
@@ -204,8 +199,11 @@
bool Curl_shutdown_started(struct Curl_easy *data, int sockindex)
{
- struct curltime *pt = &data->conn->shutdown.start[sockindex];
- return (pt->tv_sec > 0) || (pt->tv_usec > 0);
+ if(data->conn) {
+ struct curltime *pt = &data->conn->shutdown.start[sockindex];
+ return (pt->tv_sec > 0) || (pt->tv_usec > 0);
+ }
+ return FALSE;
}
/* retrieves ip address and port from a sockaddr structure. note it calls
@@ -299,7 +297,7 @@
*/
void Curl_conncontrol(struct connectdata *conn,
int ctrl /* see defines in header */
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
, const char *reason
#endif
)
@@ -309,7 +307,7 @@
associated with a transfer. */
bool closeit, is_multiplex;
DEBUGASSERT(conn);
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
(void)reason; /* useful for debugging */
#endif
is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
@@ -317,7 +315,7 @@
((ctrl == CONNCTRL_STREAM) && !is_multiplex);
if((ctrl == CONNCTRL_STREAM) && is_multiplex)
; /* stream signal on multiplex conn never affects close state */
- else if((bit)closeit != conn->bits.close) {
+ else if((curl_bit)closeit != conn->bits.close) {
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
@@ -428,8 +426,8 @@
#ifdef USE_SSL
if((ctx->ssl_mode == CURL_CF_SSL_ENABLE ||
(ctx->ssl_mode != CURL_CF_SSL_DISABLE &&
- cf->conn->handler->flags & PROTOPT_SSL)) /* we want SSL */
- && !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { /* it is missing */
+ cf->conn->scheme->flags & PROTOPT_SSL)) && /* we want SSL */
+ !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { /* it is missing */
result = Curl_cf_ssl_insert_after(cf, data);
if(result)
return result;
@@ -465,7 +463,6 @@
{
struct cf_setup_ctx *ctx = cf->ctx;
- (void)data;
CURL_TRC_CF(data, cf, "destroy");
Curl_safefree(ctx);
}
@@ -564,7 +561,7 @@
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
- DEBUGASSERT(conn->handler);
+ DEBUGASSERT(conn->scheme);
DEBUGASSERT(dns);
Curl_resolv_unlink(data, &data->state.dns[sockindex]);
@@ -572,7 +569,7 @@
#ifndef CURL_DISABLE_HTTP
if(!conn->cfilter[sockindex] &&
- conn->handler->protocol == CURLPROTO_HTTPS) {
+ conn->scheme->protocol == CURLPROTO_HTTPS) {
DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE);
result = Curl_cf_https_setup(data, conn, sockindex);
if(result)
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 01e9dfc..071b432 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -32,15 +32,13 @@
struct Curl_str;
enum alpnid Curl_alpn2alpnid(const unsigned char *name, size_t len);
-enum alpnid Curl_str2alpnid(const struct Curl_str *str);
+enum alpnid Curl_str2alpnid(const struct Curl_str *cstr);
/* generic function that returns how much time there is left to run, according
to the timeouts set */
-timediff_t Curl_timeleft_ms(struct Curl_easy *data,
- bool duringconnect);
+timediff_t Curl_timeleft_ms(struct Curl_easy *data);
timediff_t Curl_timeleft_now_ms(struct Curl_easy *data,
- const struct curltime *pnow,
- bool duringconnect);
+ const struct curltime *pnow);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
@@ -78,7 +76,7 @@
char *addr, uint16_t *port);
/*
- * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
+ * Curl_conncontrol() marks the end of a connection/stream. The 'ctrl'
* argument specifies if it is the end of a connection or a stream.
*
* For stream-based protocols (such as HTTP/2), a stream close will not cause
@@ -94,17 +92,17 @@
#define CONNCTRL_STREAM 2
void Curl_conncontrol(struct connectdata *conn,
- int closeit
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ int ctrl
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
, const char *reason
#endif
);
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
#define streamclose(x, y) Curl_conncontrol(x, CONNCTRL_STREAM, y)
#define connclose(x, y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y)
#define connkeep(x, y) Curl_conncontrol(x, CONNCTRL_KEEP, y)
-#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */
+#else /* !DEBUGBUILD || !CURLVERBOSE */
#define streamclose(x, y) Curl_conncontrol(x, CONNCTRL_STREAM)
#define connclose(x, y) Curl_conncontrol(x, CONNCTRL_CONNECTION)
#define connkeep(x, y) Curl_conncontrol(x, CONNCTRL_KEEP)
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index 9cd3e24..b8dbd7d 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -193,7 +193,7 @@
done = FALSE;
break;
case Z_BUF_ERROR:
- /* No more data to flush: just exit loop. */
+ /* No more data to flush: exit loop. */
break;
case Z_STREAM_END:
result = process_trailer(data, zp);
@@ -600,9 +600,7 @@
/* supported content decoders only for transfer encodings */
static const struct Curl_cwtype * const transfer_unencoders[] = {
-#ifndef CURL_DISABLE_HTTP
&Curl_httpchunk_unencoder,
-#endif
NULL
};
@@ -624,6 +622,9 @@
result = curlx_dyn_add(&enc, ce->name);
}
}
+ if(!result && !curlx_dyn_len(&enc))
+ result = curlx_dyn_add(&enc, CONTENT_ENCODING_DEFAULT);
+
if(!result)
return curlx_dyn_ptr(&enc);
return NULL;
@@ -679,8 +680,8 @@
for(cep = transfer_unencoders; *cep; cep++) {
const struct Curl_cwtype *ce = *cep;
if((curl_strnequal(name, ce->name, len) && !ce->name[len]) ||
- (ce->alias && curl_strnequal(name, ce->alias, len)
- && !ce->alias[len]))
+ (ce->alias && curl_strnequal(name, ce->alias, len) &&
+ !ce->alias[len]))
return ce;
}
}
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index c807222..4d53cc4 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -36,9 +36,8 @@
#include "curl_get_line.h"
#include "curl_memrchr.h"
#include "parsedate.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#include "llist.h"
-#include "bufref.h"
#include "curlx/strparse.h"
/* number of seconds in 400 days */
@@ -245,7 +244,7 @@
if(len > 1 && cookie_path[len - 1] == '/')
len--;
- return Curl_memdup0(cookie_path, len);
+ return curlx_memdup0(cookie_path, len);
}
/*
@@ -264,7 +263,7 @@
len++;
newstr = "";
}
- *str = Curl_memdup0(newstr, len);
+ *str = curlx_memdup0(newstr, len);
if(!*str)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -288,10 +287,10 @@
/*
* If the earliest expiration timestamp in the jar is in the future we can
* skip scanning the whole jar and instead exit early as there will not be
- * any cookies to evict. If we need to evict however, reset the
- * next_expiration counter in order to track the next one. In case the
- * recorded first expiration is the max offset, then perform the safe
- * fallback of checking all cookies.
+ * any cookies to evict. If we need to evict, reset the next_expiration
+ * counter in order to track the next one. In case the recorded first
+ * expiration is the max offset, then perform the safe fallback of checking
+ * all cookies.
*/
if(now < ci->next_expiration &&
ci->next_expiration != CURL_OFF_T_MAX)
@@ -331,7 +330,7 @@
return FALSE;
else {
/* there must be a dot present, but that dot must not be a trailing dot */
- char *dot = memchr(domain, '.', len);
+ const char *dot = memchr(domain, '.', len);
if(dot) {
size_t i = dot - domain;
if((len - i) > 1)
@@ -367,15 +366,14 @@
/* The maximum length we accept a date string for the 'expire' keyword. The
standard date formats are within the 30 bytes range. This adds an extra
- margin just to make sure it realistically works with what is used out
- there.
+ margin to make sure it realistically works with what is used out there.
*/
#define MAX_DATE_LENGTH 80
-#define COOKIE_NAME 0
-#define COOKIE_VALUE 1
+#define COOKIE_NAME 0
+#define COOKIE_VALUE 1
#define COOKIE_DOMAIN 2
-#define COOKIE_PATH 3
+#define COOKIE_PATH 3
#define COOKIE_PIECES 4 /* the list above */
@@ -398,7 +396,7 @@
/* No path was given in the header line, set the default */
const char *endslash = strrchr(path, '/');
if(endslash)
- plen = (endslash - path + 1); /* include end slash */
+ plen = endslash - path + 1; /* include end slash */
else
plen = strlen(path);
}
@@ -694,7 +692,7 @@
ptr++;
len--;
}
- co->domain = Curl_memdup0(ptr, len);
+ co->domain = curlx_memdup0(ptr, len);
if(!co->domain)
return CURLE_OUT_OF_MEMORY;
break;
@@ -737,7 +735,7 @@
return CURLE_OK;
break;
case 5:
- co->name = Curl_memdup0(ptr, len);
+ co->name = curlx_memdup0(ptr, len);
if(!co->name)
return CURLE_OUT_OF_MEMORY;
else {
@@ -749,7 +747,7 @@
}
break;
case 6:
- co->value = Curl_memdup0(ptr, len);
+ co->value = curlx_memdup0(ptr, len);
if(!co->value)
return CURLE_OUT_OF_MEMORY;
break;
@@ -783,7 +781,7 @@
* dereference it.
*/
DEBUGF(infof(data, "PSL check set-cookie '%s' for domain=%s in %s",
- co->name, co->domain, domain));
+ co->name, co->domain, domain));
if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
bool acceptable = FALSE;
char lcase[256];
@@ -814,7 +812,7 @@
(void)co;
(void)domain;
DEBUGF(infof(data, "NO PSL to check set-cookie '%s' for domain=%s in %s",
- co->name, co->domain, domain));
+ co->name, co->domain, domain));
#endif
return FALSE;
}
@@ -1008,7 +1006,7 @@
goto fail;
/* clone the stack struct into heap */
- co = Curl_memdup(&comem, sizeof(comem));
+ co = curlx_memdup(&comem, sizeof(comem));
if(!co) {
co = &comem;
result = CURLE_OUT_OF_MEMORY;
@@ -1169,7 +1167,7 @@
data->state.cookie_engine = TRUE;
while(list) {
result = cookie_load(data, list->data, data->cookies,
- data->set.cookiesession);
+ (bool)data->set.cookiesession);
if(result)
break;
list = list->next;
@@ -1234,7 +1232,7 @@
bool Curl_secure_context(struct connectdata *conn, const char *host)
{
- return conn->handler->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS) ||
+ return conn->scheme->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS) ||
curl_strequal("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "::1");
@@ -1315,8 +1313,8 @@
if(matches) {
/*
* Now we need to make sure that if there is a name appearing more than
- * once, the longest specified path version comes first. To make this
- * the swiftest way, we just sort them all based on path length.
+ * once, the longest specified path version comes first. To make this the
+ * swiftest way, we sort them all based on path length.
*/
struct Cookie **array;
size_t i;
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index cbc7b74..fabd04d 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -111,15 +111,18 @@
bool Curl_secure_context(struct connectdata *conn, const char *host);
CURLcode Curl_cookie_add(struct Curl_easy *data,
- struct CookieInfo *c, bool header,
- bool noexpiry, const char *lineptr,
- const char *domain, const char *path,
+ struct CookieInfo *ci,
+ bool httpheader,
+ bool noexpire,
+ const char *lineptr,
+ const char *domain,
+ const char *path,
bool secure) WARN_UNUSED_RESULT;
CURLcode Curl_cookie_getlist(struct Curl_easy *data, struct connectdata *conn,
bool *okay, const char *host,
struct Curl_llist *list) WARN_UNUSED_RESULT;
-void Curl_cookie_clearall(struct CookieInfo *cookies);
-void Curl_cookie_clearsess(struct CookieInfo *cookies);
+void Curl_cookie_clearall(struct CookieInfo *ci);
+void Curl_cookie_clearsess(struct CookieInfo *ci);
#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
#define Curl_cookie_list(x) NULL
@@ -130,7 +133,7 @@
#define Curl_flush_cookies(x, y) Curl_nop_stmt
#else
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup);
-void Curl_cookie_cleanup(struct CookieInfo *c);
+void Curl_cookie_cleanup(struct CookieInfo *ci);
struct CookieInfo *Curl_cookie_init(void);
struct curl_slist *Curl_cookie_list(struct Curl_easy *data);
CURLcode Curl_cookie_loadfiles(struct Curl_easy *data) WARN_UNUSED_RESULT;
diff --git a/Utilities/cmcurl/lib/cshutdn.c b/Utilities/cmcurl/lib/cshutdn.c
index 84e5b2a..308f2aa 100644
--- a/Utilities/cmcurl/lib/cshutdn.c
+++ b/Utilities/cmcurl/lib/cshutdn.c
@@ -43,14 +43,14 @@
{
if(!conn->bits.shutdown_handler) {
- if(conn->handler && conn->handler->disconnect) {
+ if(conn->scheme && conn->scheme->run->disconnect) {
/* Some disconnect handlers do a blocking wait on server responses.
* FTP/IMAP/SMTP and SFTP are among them. When using the internal
* handle, set an overall short timeout so we do not hang for the
* default 120 seconds. */
if(data->state.internal) {
data->set.timeout = DEFAULT_SHUTDOWN_TIMEOUT_MS;
- (void)Curl_pgrsTime(data, TIMER_STARTOP);
+ Curl_pgrsTime(data, TIMER_STARTOP);
}
/* This is set if protocol-specific cleanups should be made */
@@ -59,7 +59,7 @@
conn->connection_id, conn->bits.aborted));
/* There are protocol handlers that block on retrieving
* server responses here (FTP). Set a short timeout. */
- conn->handler->disconnect(data, conn, conn->bits.aborted);
+ conn->scheme->run->disconnect(data, conn, (bool)conn->bits.aborted);
}
conn->bits.shutdown_handler = TRUE;
@@ -76,6 +76,10 @@
/* We expect to be attached when called */
DEBUGASSERT(data->conn == conn);
+ if(!Curl_shutdown_started(data, FIRSTSOCKET)) {
+ Curl_shutdown_start(data, FIRSTSOCKET, 0);
+ }
+
cshutdn_run_conn_handler(data, conn);
if(conn->bits.shutdown_filters) {
@@ -176,13 +180,13 @@
}
if(e) {
- SIGPIPE_VARIABLE(pipe_st);
+ struct Curl_sigpipe_ctx sigpipe_ctx;
conn = Curl_node_elem(e);
Curl_node_remove(e);
- sigpipe_init(&pipe_st);
- sigpipe_apply(data, &pipe_st);
+ sigpipe_init(&sigpipe_ctx);
+ sigpipe_apply(data, &sigpipe_ctx);
Curl_cshutdn_terminate(data, conn, FALSE);
- sigpipe_restore(&pipe_st);
+ sigpipe_restore(&sigpipe_ctx);
return TRUE;
}
return FALSE;
@@ -222,7 +226,8 @@
}
static void cshutdn_perform(struct cshutdn *cshutdn,
- struct Curl_easy *data)
+ struct Curl_easy *data,
+ struct Curl_sigpipe_ctx *sigpipe_ctx)
{
struct Curl_llist_node *e = Curl_llist_head(&cshutdn->list);
struct Curl_llist_node *enext;
@@ -235,6 +240,7 @@
CURL_TRC_M(data, "[SHUTDOWN] perform on %zu connections",
Curl_llist_count(&cshutdn->list));
+ sigpipe_apply(data, sigpipe_ctx);
while(e) {
enext = Curl_node_next(e);
conn = Curl_node_elem(e);
@@ -263,20 +269,19 @@
{
struct curltime started = *Curl_pgrs_now(data);
struct Curl_llist_node *e;
- SIGPIPE_VARIABLE(pipe_st);
+ struct Curl_sigpipe_ctx sigpipe_ctx;
DEBUGASSERT(cshutdn);
DEBUGASSERT(data);
CURL_TRC_M(data, "[SHUTDOWN] shutdown all");
- sigpipe_init(&pipe_st);
- sigpipe_apply(data, &pipe_st);
+ sigpipe_init(&sigpipe_ctx);
while(Curl_llist_head(&cshutdn->list)) {
timediff_t spent_ms;
int remain_ms;
- cshutdn_perform(cshutdn, data);
+ cshutdn_perform(cshutdn, data, &sigpipe_ctx);
if(!Curl_llist_head(&cshutdn->list)) {
CURL_TRC_M(data, "[SHUTDOWN] shutdown finished cleanly");
@@ -308,7 +313,7 @@
}
DEBUGASSERT(!Curl_llist_count(&cshutdn->list));
- sigpipe_restore(&pipe_st);
+ sigpipe_restore(&sigpipe_ctx);
}
int Curl_cshutdn_init(struct cshutdn *cshutdn,
@@ -326,7 +331,7 @@
{
if(cshutdn->initialised && data) {
int timeout_ms = 0;
- /* Just for testing, run graceful shutdown */
+ /* for testing, run graceful shutdown */
#ifdef DEBUGBUILD
{
const char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
@@ -396,8 +401,8 @@
/* Add the connection to our shutdown list for non-blocking shutdown
* during multi processing. */
- if(max_total > 0 && (max_total <=
- (conns_in_pool + Curl_llist_count(&cshutdn->list)))) {
+ if(max_total > 0 &&
+ (max_total <= (conns_in_pool + Curl_llist_count(&cshutdn->list)))) {
CURL_TRC_M(data, "[SHUTDOWN] discarding oldest shutdown connection "
"due to connection limit of %zu", max_total);
cshutdn_destroy_oldest(cshutdn, data, NULL);
@@ -418,38 +423,11 @@
conn->connection_id, Curl_llist_count(&cshutdn->list));
}
-static void cshutdn_multi_socket(struct cshutdn *cshutdn,
- struct Curl_easy *data,
- curl_socket_t s)
-{
- struct Curl_llist_node *e;
- struct connectdata *conn;
- bool done;
-
- DEBUGASSERT(cshutdn->multi->socket_cb);
- e = Curl_llist_head(&cshutdn->list);
- while(e) {
- conn = Curl_node_elem(e);
- if(s == conn->sock[FIRSTSOCKET] || s == conn->sock[SECONDARYSOCKET]) {
- Curl_cshutdn_run_once(data, conn, &done);
- if(done || cshutdn_update_ev(cshutdn, data, conn)) {
- Curl_node_remove(e);
- Curl_cshutdn_terminate(data, conn, FALSE);
- }
- break;
- }
- e = Curl_node_next(e);
- }
-}
-
void Curl_cshutdn_perform(struct cshutdn *cshutdn,
struct Curl_easy *data,
- curl_socket_t s)
+ struct Curl_sigpipe_ctx *sigpipe_ctx)
{
- if((s == CURL_SOCKET_TIMEOUT) || (!cshutdn->multi->socket_cb))
- cshutdn_perform(cshutdn, data);
- else
- cshutdn_multi_socket(cshutdn, data, s);
+ cshutdn_perform(cshutdn, data, sigpipe_ctx);
}
/* return fd_set info about the shutdown connections */
@@ -480,17 +458,10 @@
curl_socket_t sock = ps.sockets[i];
if(!FDSET_SOCK(sock))
continue;
-#ifdef __DJGPP__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Warith-conversion"
-#endif
if(ps.actions[i] & CURL_POLL_IN)
FD_SET(sock, read_fd_set);
if(ps.actions[i] & CURL_POLL_OUT)
FD_SET(sock, write_fd_set);
-#ifdef __DJGPP__
-#pragma GCC diagnostic pop
-#endif
if((ps.actions[i] & (CURL_POLL_OUT | CURL_POLL_IN)) &&
((int)sock > *maxfd))
*maxfd = (int)sock;
diff --git a/Utilities/cmcurl/lib/cshutdn.h b/Utilities/cmcurl/lib/cshutdn.h
index 0a15d39..9030474 100644
--- a/Utilities/cmcurl/lib/cshutdn.h
+++ b/Utilities/cmcurl/lib/cshutdn.h
@@ -30,6 +30,7 @@
struct Curl_waitfds;
struct Curl_multi;
struct Curl_share;
+struct Curl_sigpipe_ctx;
/* Run the shutdown of the connection once.
* Will shortly attach/detach `data` to `conn` while doing so.
@@ -40,12 +41,12 @@
bool *done);
/* Terminates the connection, e.g. closes and destroys it.
- * If `run_shutdown` is TRUE, the shutdown will be run once before
+ * If `do_shutdown` is TRUE, the shutdown will be run once before
* terminating it.
* Takes ownership of `conn`. */
void Curl_cshutdn_terminate(struct Curl_easy *data,
struct connectdata *conn,
- bool run_shutdown);
+ bool do_shutdown);
/* A `cshutdown` is always owned by a multi handle to maintain
* the connections to be shut down. It registers timers and
@@ -97,10 +98,9 @@
fd_set *read_fd_set, fd_set *write_fd_set,
int *maxfd);
-/* Run shut down connections using socket. If socket is CURL_SOCKET_TIMEOUT,
- * run maintenance on all connections. */
+/* Run maintenance on all connections. */
void Curl_cshutdn_perform(struct cshutdn *cshutdn,
struct Curl_easy *data,
- curl_socket_t s);
+ struct Curl_sigpipe_ctx *sigpipe_ctx);
#endif /* HEADER_CURL_CSHUTDN_H */
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 61c8b18..43d398d 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -62,9 +62,9 @@
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
/* workaround icc 9.1 optimizer issue */
-# define vqualifier volatile
+# define vqualifier volatile
#else
-# define vqualifier
+# define vqualifier
#endif
void Curl_freeaddrinfo(struct Curl_addrinfo *cahead)
@@ -115,8 +115,8 @@
for(ai = aihead; ai != NULL; ai = ai->ai_next) {
size_t namelen = ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0;
- /* ignore elements with unsupported address family, */
- /* settle family-specific sockaddr structure size. */
+ /* ignore elements with unsupported address family,
+ settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
#ifdef USE_IPV6
@@ -140,8 +140,8 @@
break;
}
- /* copy each structure member individually, member ordering, */
- /* size, or padding might be different for each platform. */
+ /* copy each structure member individually, member ordering,
+ size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
@@ -404,19 +404,19 @@
* Given an IPv4 or IPv6 dotted string address, this converts it to a proper
* allocated Curl_addrinfo struct and returns it.
*/
-CURLcode Curl_str2addr(const char *address, int port,
+CURLcode Curl_str2addr(const char *dotted, int port,
struct Curl_addrinfo **addrp)
{
struct in_addr in;
- if(curlx_inet_pton(AF_INET, address, &in) > 0)
+ if(curlx_inet_pton(AF_INET, dotted, &in) > 0)
/* This is a dotted IP address 123.123.123.123-style */
- return ip2addr(addrp, AF_INET, &in, address, port);
+ return ip2addr(addrp, AF_INET, &in, dotted, port);
#ifdef USE_IPV6
{
struct in6_addr in6;
- if(curlx_inet_pton(AF_INET6, address, &in6) > 0)
+ if(curlx_inet_pton(AF_INET6, dotted, &in6) > 0)
/* This is a dotted IPv6 address ::1-style */
- return ip2addr(addrp, AF_INET6, &in6, address, port);
+ return ip2addr(addrp, AF_INET6, &in6, dotted, port);
}
#endif
return CURLE_BAD_FUNCTION_ARGUMENT; /* bad input format */
@@ -485,7 +485,7 @@
}
#endif
-#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
+#if defined(CURL_MEMDEBUG) && defined(HAVE_GETADDRINFO) && \
defined(HAVE_FREEADDRINFO)
/*
* curl_dbg_freeaddrinfo()
@@ -515,9 +515,9 @@
freeaddrinfo(freethis);
#endif
}
-#endif /* CURLDEBUG && HAVE_FREEADDRINFO */
+#endif /* CURL_MEMDEBUG && HAVE_FREEADDRINFO */
-#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
+#if defined(CURL_MEMDEBUG) && defined(HAVE_GETADDRINFO)
/*
* curl_dbg_getaddrinfo()
*
@@ -553,7 +553,7 @@
curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", source, line);
return res;
}
-#endif /* CURLDEBUG && HAVE_GETADDRINFO */
+#endif /* CURL_MEMDEBUG && HAVE_GETADDRINFO */
#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS)
/*
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h
index ca80f3a..f464b5e 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -38,7 +38,6 @@
#ifdef __VMS
# include <in.h>
# include <inet.h>
-# include <stdlib.h>
#endif
/*
@@ -73,20 +72,21 @@
#endif
bool Curl_is_ipaddr(const char *address);
-CURLcode Curl_str2addr(const char *dotted, int port, struct Curl_addrinfo **);
+CURLcode Curl_str2addr(const char *dotted, int port,
+ struct Curl_addrinfo **addrp);
#ifdef USE_UNIX_SOCKETS
struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
bool abstract);
#endif
-#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
+#if defined(CURL_MEMDEBUG) && defined(HAVE_GETADDRINFO) && \
defined(HAVE_FREEADDRINFO)
void curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line,
const char *source);
#endif
-#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
+#if defined(CURL_MEMDEBUG) && defined(HAVE_GETADDRINFO)
int curl_dbg_getaddrinfo(const char *hostname, const char *service,
const struct addrinfo *hints,
struct addrinfo **result, int line,
diff --git a/Utilities/cmcurl/lib/curl_config-cmake.h.in b/Utilities/cmcurl/lib/curl_config-cmake.h.in
index df06ae7..4292c2b 100644
--- a/Utilities/cmcurl/lib/curl_config-cmake.h.in
+++ b/Utilities/cmcurl/lib/curl_config-cmake.h.in
@@ -27,6 +27,9 @@
/* Default SSL backend */
#cmakedefine CURL_DEFAULT_SSL_BACKEND "${CURL_DEFAULT_SSL_BACKEND}"
+/* Use native CA store */
+#cmakedefine CURL_CA_NATIVE 1
+
/* disables alt-svc */
#cmakedefine CURL_DISABLE_ALTSVC 1
@@ -153,9 +156,6 @@
/* disables TFTP */
#cmakedefine CURL_DISABLE_TFTP 1
-/* disables curl_easy_setopt()/curl_easy_getinfo() type checking */
-#cmakedefine CURL_DISABLE_TYPECHECK 1
-
/* disables verbose strings */
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
@@ -317,6 +317,12 @@
/* MIT Kerberos version */
#cmakedefine CURL_KRB5_VERSION ${CURL_KRB5_VERSION}
+/* BoringSSL version */
+#cmakedefine CURL_BORINGSSL_VERSION ${CURL_BORINGSSL_VERSION}
+
+/* Patch stamp */
+#cmakedefine CURL_PATCHSTAMP ${CURL_PATCHSTAMP}
+
/* Define to 1 if you have the <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1
@@ -387,17 +393,9 @@
/* Define to 1 if you have a working localtime_r function. */
#cmakedefine HAVE_LOCALTIME_R 1
-/* Define to 1 if the compiler supports the 'long long' data type. */
-#if KWIML_ABI_SIZEOF_LONG_LONG
-# define HAVE_LONGLONG 1
-#endif
-
/* Define to 1 if you have the 'suseconds_t' data type. */
#cmakedefine HAVE_SUSECONDS_T 1
-/* Define to 1 if you have the MSG_NOSIGNAL flag. */
-#cmakedefine HAVE_MSG_NOSIGNAL 1
-
/* Define to 1 if you have the <netdb.h> header file. */
#cmakedefine HAVE_NETDB_H 1
@@ -467,9 +465,6 @@
/* Define to 1 if you have the sendmmsg function. */
#cmakedefine HAVE_SENDMMSG 1
-/* Define to 1 if you have the <stdint.h> header file. */
-#cmakedefine HAVE_STDINT_H 1
-
/* Define to 1 if you have the 'fsetxattr' function. */
#cmakedefine HAVE_FSETXATTR 1
@@ -482,12 +477,6 @@
/* Define to 1 if you have the `setlocale' function. */
#cmakedefine HAVE_SETLOCALE 1
-/* Define to 1 if you have the `setmode' function. */
-#cmakedefine HAVE_SETMODE 1
-
-/* Define to 1 if you have the `_setmode' function. */
-#cmakedefine HAVE__SETMODE 1
-
/* Define to 1 if you have the `setrlimit' function. */
#cmakedefine HAVE_SETRLIMIT 1
@@ -533,9 +522,6 @@
/* Define to 1 if you have the strcmpi function. */
#cmakedefine HAVE_STRCMPI 1
-/* Define to 1 if you have the strdup function. */
-#cmakedefine HAVE_STRDUP 1
-
/* Define to 1 if you have the strerror_r function. */
#cmakedefine HAVE_STRERROR_R 1
@@ -621,12 +607,12 @@
#cmakedefine CURL_OS ${CURL_OS}
/*
- Note: SIZEOF_* variables are fetched with CMake through check_type_size().
- As per CMake documentation on CheckTypeSize, C preprocessor code is
- generated by CMake into SIZEOF_*_CODE. This is what we use in the
- following statements.
+ Note: SIZEOF_* variables are fetched with CMake through check_type_size().
+ As per CMake documentation on CheckTypeSize, C preprocessor code is
+ generated by CMake into SIZEOF_*_CODE. This is what we use in the
+ following statements.
- Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html
+ Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html
*/
/* The size of `int', as computed by sizeof. */
@@ -646,9 +632,6 @@
# define SIZEOF___INT64 KWIML_ABI_SIZEOF___INT64
#endif
-/* The size of `long long', as computed by sizeof. */
-${SIZEOF_LONG_LONG_CODE}
-
/* The size of `off_t', as computed by sizeof. */
${SIZEOF_OFF_T_CODE}
@@ -749,34 +732,31 @@
automatically */
#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1
-/* to enable NGHTTP2 */
+/* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1
/* to enable NGTCP2 */
#cmakedefine USE_NGTCP2 1
-/* to enable NGHTTP3 */
+/* to enable NGHTTP3 */
#cmakedefine USE_NGHTTP3 1
/* to enable quiche */
#cmakedefine USE_QUICHE 1
-/* to enable openssl + nghttp3 */
-#cmakedefine USE_OPENSSL_QUIC 1
-
/* to enable openssl + ngtcp2 + nghttp3 */
#cmakedefine OPENSSL_QUIC_API2 1
/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
-/* if Unix domain sockets are enabled */
+/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS 1
/* to enable SSPI support */
#cmakedefine USE_WINDOWS_SSPI 1
-/* to enable Windows SSL */
+/* to enable Windows SSL */
#cmakedefine USE_SCHANNEL 1
/* if Watt-32 is in use */
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index 8e35ede..dde956c 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -251,8 +251,8 @@
static int loop(const unsigned char *pattern, const unsigned char *string,
int maxstars)
{
- const unsigned char *p = (const unsigned char *)pattern;
- const unsigned char *s = (const unsigned char *)string;
+ const unsigned char *p = pattern;
+ const unsigned char *s = string;
unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
for(;;) {
diff --git a/Utilities/cmcurl/lib/curl_fopen.c b/Utilities/cmcurl/lib/curl_fopen.c
index 9559c0d..b7a67aa 100644
--- a/Utilities/cmcurl/lib/curl_fopen.c
+++ b/Utilities/cmcurl/lib/curl_fopen.c
@@ -23,7 +23,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
!defined(CURL_DISABLE_HSTS)
#include "urldata.h"
@@ -89,7 +89,7 @@
unsigned char randbuf[41];
char *tempstore = NULL;
#ifndef _WIN32
- struct_stat sb;
+ curlx_struct_stat sb;
#endif
int fd = -1;
char *dir = NULL;
@@ -99,7 +99,7 @@
*fh = curlx_fopen(filename, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
- if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
+ if(curlx_fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
return CURLE_OK;
}
curlx_fclose(*fh);
@@ -125,8 +125,8 @@
result = CURLE_WRITE_ERROR;
#ifdef _WIN32
- fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL,
- S_IREAD | S_IWRITE);
+ fd = curlx_open(tempstore, _O_WRONLY | _O_CREAT | _O_EXCL,
+ _S_IREAD | _S_IWRITE);
#elif (defined(ANDROID) || defined(__ANDROID__)) && \
(defined(__i386__) || defined(__arm__))
fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL,
@@ -147,7 +147,7 @@
fail:
if(fd != -1) {
- close(fd);
+ curlx_close(fd);
unlink(tempstore);
}
diff --git a/Utilities/cmcurl/lib/curl_get_line.c b/Utilities/cmcurl/lib/curl_get_line.c
index 46c1287..85b3525 100644
--- a/Utilities/cmcurl/lib/curl_get_line.c
+++ b/Utilities/cmcurl/lib/curl_get_line.c
@@ -23,13 +23,11 @@
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
!defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
-#define appendnl(b) curlx_dyn_addn(buf, "\n", 1)
-
/*
* Curl_get_line() returns only complete whole lines that end with newline.
* When 'eof' is set TRUE, the last line has been read.
@@ -41,7 +39,7 @@
curlx_dyn_reset(buf);
while(1) {
size_t rlen;
- char *b = fgets(buffer, sizeof(buffer), input);
+ const char *b = fgets(buffer, sizeof(buffer), input);
*eof = feof(input);
@@ -60,7 +58,7 @@
return CURLE_OK; /* all good */
if(*eof)
/* append a newline */
- return appendnl(buf);
+ return curlx_dyn_addn(buf, "\n", 1);
/* otherwise get next line to append */
}
/* UNREACHABLE */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index 8c82f77..c0eb1c4 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -384,6 +384,7 @@
return gss_delete_sec_context(min, context, output_token);
}
+#ifdef CURLVERBOSE
#define GSS_LOG_BUFFER_LEN 1024
static size_t display_gss_error(OM_uint32 status, int type,
char *buf, size_t len)
@@ -437,11 +438,8 @@
display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
infof(data, "%s%s", prefix, buf);
-#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)data;
- (void)prefix;
-#endif
}
+#endif /* CURLVERBOSE */
#if defined(__GNUC__) && defined(__APPLE__)
#pragma GCC diagnostic pop
diff --git a/Utilities/cmcurl/lib/curl_gssapi.h b/Utilities/cmcurl/lib/curl_gssapi.h
index 8c09c72..0d36097 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.h
+++ b/Utilities/cmcurl/lib/curl_gssapi.h
@@ -47,9 +47,19 @@
gss_ctx_id_t *context_handle,
gss_buffer_t output_token);
+#ifdef CURLVERBOSE
/* Helper to log a GSS-API error status */
void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
OM_uint32 major, OM_uint32 minor);
+#else
+#define Curl_gss_log_error(data, prefix, major, minor) \
+ do { \
+ (void)(data); \
+ (void)(prefix); \
+ (void)(major); \
+ (void)(minor); \
+ } while(0)
+#endif
/* Define our privacy and integrity protection values */
#define GSSAUTH_P_NONE 1
diff --git a/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h
index 4759ff6..b9f218f 100644
--- a/Utilities/cmcurl/lib/curl_hmac.h
+++ b/Utilities/cmcurl/lib/curl_hmac.h
@@ -57,10 +57,10 @@
struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams,
const unsigned char *key,
unsigned int keylen);
-int Curl_HMAC_update(struct HMAC_context *context,
+int Curl_HMAC_update(struct HMAC_context *ctxt,
const unsigned char *data,
unsigned int len);
-int Curl_HMAC_final(struct HMAC_context *context, unsigned char *result);
+int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *output);
CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
const unsigned char *key, const size_t keylen,
diff --git a/Utilities/cmcurl/lib/curl_ldap.h b/Utilities/cmcurl/lib/curl_ldap.h
index 5ef32a5..7c1e1c4 100644
--- a/Utilities/cmcurl/lib/curl_ldap.h
+++ b/Utilities/cmcurl/lib/curl_ldap.h
@@ -23,15 +23,11 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#ifndef CURL_DISABLE_LDAP
-extern const struct Curl_handler Curl_handler_ldap;
+extern const struct Curl_protocol Curl_protocol_ldap;
-#if !defined(CURL_DISABLE_LDAPS) && \
- ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
- (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
-extern const struct Curl_handler Curl_handler_ldaps;
-#endif
+extern const struct Curl_scheme Curl_scheme_ldap;
+extern const struct Curl_scheme Curl_scheme_ldaps;
void Curl_ldap_version(char *buf, size_t bufsz);
-#endif
+
#endif /* HEADER_CURL_LDAP_H */
diff --git a/Utilities/cmcurl/lib/curl_md5.h b/Utilities/cmcurl/lib/curl_md5.h
index 16272c7..042c5f5 100644
--- a/Utilities/cmcurl/lib/curl_md5.h
+++ b/Utilities/cmcurl/lib/curl_md5.h
@@ -58,7 +58,7 @@
struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params);
CURLcode Curl_MD5_update(struct MD5_context *context,
- const unsigned char *data,
+ const unsigned char *input,
unsigned int len);
CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result);
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 2f4f7c3..4a9433b 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -57,11 +57,11 @@
#endif
#if defined(USE_OPENSSL) && defined(HAVE_DES_ECB_ENCRYPT)
- #define USE_OPENSSL_DES
+# define USE_OPENSSL_DES
#elif defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT)
- #define USE_OPENSSL_DES
+# define USE_OPENSSL_DES
#elif defined(USE_MBEDTLS) && defined(HAVE_MBEDTLS_DES_CRYPT_ECB)
- #define USE_MBEDTLS_DES
+# define USE_MBEDTLS_DES
#endif
#ifdef USE_OPENSSL_DES
@@ -84,18 +84,14 @@
# define DES_set_key_unchecked wolfSSL_DES_set_key_unchecked
# define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt
# define DESKEY(x) ((WOLFSSL_DES_key_schedule *)(x))
-
-# if defined(LIBWOLFSSL_VERSION_HEX) && \
- (LIBWOLFSSL_VERSION_HEX >= 0x05007006)
+# if defined(LIBWOLFSSL_VERSION_HEX) && LIBWOLFSSL_VERSION_HEX >= 0x05007006
# define DES_ENCRYPT WC_DES_ENCRYPT
# define DES_DECRYPT WC_DES_DECRYPT
# endif
-
# else
# define DESKEY(x) &x
# endif
#endif
-#define DESKEYARG(x) *x
#elif defined(USE_GNUTLS)
@@ -141,7 +137,7 @@
*
* bytes [in/out] - The data whose parity bits are to be adjusted for
* odd parity.
- * len [out] - The length of the data.
+ * len [in] - The length of the data.
*/
static void curl_des_set_odd_parity(unsigned char *bytes, size_t len)
{
@@ -182,8 +178,7 @@
* Turns a 56-bit key into a 64-bit, odd parity key and sets the key. The
* key schedule ks is also set.
*/
-static void setup_des_key(const unsigned char *key_56,
- DES_key_schedule DESKEYARG(ks))
+static void setup_des_key(const unsigned char *key_56, DES_key_schedule *ks)
{
DES_cblock key;
@@ -307,7 +302,7 @@
return TRUE;
}
-#endif /* USE_WIN32_CRYPTO */
+#endif /* crypto backends */
/*
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
@@ -340,7 +335,7 @@
des_encrypt(&des, 8, results + 8, plaintext);
setup_des_key(keys + 14, &des);
des_encrypt(&des, 8, results + 16, plaintext);
-#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) || \
+#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
@@ -386,7 +381,7 @@
des_encrypt(&des, 8, lmbuffer, magic);
setup_des_key(pw + 7, &des);
des_encrypt(&des, 8, lmbuffer + 8, magic);
-#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) || \
+#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -404,24 +399,10 @@
size_t i;
for(i = 0; i < srclen; i++) {
dest[2 * i] = (unsigned char)src[i];
- dest[2 * i + 1] = '\0';
+ dest[(2 * i) + 1] = '\0';
}
}
-#ifndef USE_WINDOWS_SSPI
-
-static void ascii_uppercase_to_unicode_le(unsigned char *dest,
- const char *src, size_t srclen)
-{
- size_t i;
- for(i = 0; i < srclen; i++) {
- dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i]));
- dest[2 * i + 1] = '\0';
- }
-}
-
-#endif /* !USE_WINDOWS_SSPI */
-
/*
* Set up nt hashed passwords
* @unittest: 1600
@@ -505,6 +486,16 @@
#endif
}
+static void ascii_uppercase_to_unicode_le(unsigned char *dest,
+ const char *src, size_t srclen)
+{
+ size_t i;
+ for(i = 0; i < srclen; i++) {
+ dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i]));
+ dest[(2 * i) + 1] = '\0';
+ }
+}
+
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
* (uppercase UserName + Domain) as the data
*/
@@ -554,9 +545,9 @@
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
- unsigned char *challenge_client,
- struct ntlmdata *ntlm,
+CURLcode Curl_ntlm_core_mk_ntlmv2_resp(const unsigned char *ntlmv2hash,
+ const unsigned char *challenge_client,
+ const struct ntlmdata *ntlm,
unsigned char **ntresp,
unsigned int *ntresp_len)
{
@@ -647,9 +638,9 @@
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
- unsigned char *challenge_client,
- unsigned char *challenge_server,
+CURLcode Curl_ntlm_core_mk_lmv2_resp(const unsigned char *ntlmv2hash,
+ const unsigned char *challenge_client,
+ const unsigned char *challenge_server,
unsigned char *lmresp)
{
unsigned char data[16];
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h
index 947b836..f96bf0a 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.h
@@ -55,15 +55,15 @@
unsigned char *ntlmhash,
unsigned char *ntlmv2hash);
-CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
- unsigned char *challenge_client,
- struct ntlmdata *ntlm,
+CURLcode Curl_ntlm_core_mk_ntlmv2_resp(const unsigned char *ntlmv2hash,
+ const unsigned char *challenge_client,
+ const struct ntlmdata *ntlm,
unsigned char **ntresp,
unsigned int *ntresp_len);
-CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
- unsigned char *challenge_client,
- unsigned char *challenge_server,
+CURLcode Curl_ntlm_core_mk_lmv2_resp(const unsigned char *ntlmv2hash,
+ const unsigned char *challenge_client,
+ const unsigned char *challenge_server,
unsigned char *lmresp);
#endif /* !USE_WINDOWS_SSPI */
diff --git a/Utilities/cmcurl/lib/curl_printf.h b/Utilities/cmcurl/lib/curl_printf.h
index 207ba71..3b1a5af 100644
--- a/Utilities/cmcurl/lib/curl_printf.h
+++ b/Utilities/cmcurl/lib/curl_printf.h
@@ -28,10 +28,10 @@
#define MERR_MEM 1
#define MERR_TOO_LARGE 2
-/* Lower-case digits. */
+/* Lower-case digits. */
extern const unsigned char Curl_ldigits[];
-/* Upper-case digits. */
+/* Upper-case digits. */
extern const unsigned char Curl_udigits[];
#endif /* HEADER_CURL_PRINTF_H */
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
index 14218f1..9bbafa4 100644
--- a/Utilities/cmcurl/lib/curl_range.c
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -30,10 +30,8 @@
/* Only include this function if one or more of FTP, FILE are enabled. */
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
-/*
- Check if this is a range download, and if so, set the internal variables
- properly.
-*/
+/* Check if this is a range download, and if so, set the internal variables
+ properly. */
CURLcode Curl_range(struct Curl_easy *data)
{
if(data->state.use_range && data->state.range) {
@@ -56,7 +54,7 @@
else if(!first_num) {
/* -Y */
if(!to)
- /* "-0" is just wrong */
+ /* "-0" is wrong */
return CURLE_RANGE_ERROR;
data->req.maxdownload = to;
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index 98816f8..75b8091 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -24,10 +24,11 @@
***************************************************************************/
#include "curl_setup.h"
-#ifdef USE_LIBRTMP
-
#include "curl_rtmp.h"
#include "urldata.h"
+
+#ifdef USE_LIBRTMP
+
#include "url.h"
#include "curlx/nonblock.h"
#include "progress.h" /* for Curl_pgrsSetUploadSize */
@@ -47,172 +48,9 @@
/* meta key for storing RTMP* at connection */
#define CURL_META_RTMP_CONN "meta:proto:rtmp:conn"
-
-static CURLcode rtmp_setup_connection(struct Curl_easy *data,
- struct connectdata *conn);
-static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
-static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature);
-static CURLcode rtmp_connect(struct Curl_easy *data, bool *done);
-static CURLcode rtmp_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead);
-
static Curl_recv rtmp_recv;
static Curl_send rtmp_send;
-/*
- * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu/
- */
-
-const struct Curl_handler Curl_handler_rtmp = {
- "rtmp", /* scheme */
- rtmp_setup_connection, /* setup_connection */
- rtmp_do, /* do_it */
- rtmp_done, /* done */
- ZERO_NULL, /* do_more */
- rtmp_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_RTMP, /* defport */
- CURLPROTO_RTMP, /* protocol */
- CURLPROTO_RTMP, /* family */
- PROTOPT_NONE /* flags */
-};
-
-const struct Curl_handler Curl_handler_rtmpt = {
- "rtmpt", /* scheme */
- rtmp_setup_connection, /* setup_connection */
- rtmp_do, /* do_it */
- rtmp_done, /* done */
- ZERO_NULL, /* do_more */
- rtmp_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_RTMPT, /* defport */
- CURLPROTO_RTMPT, /* protocol */
- CURLPROTO_RTMPT, /* family */
- PROTOPT_NONE /* flags */
-};
-
-const struct Curl_handler Curl_handler_rtmpe = {
- "rtmpe", /* scheme */
- rtmp_setup_connection, /* setup_connection */
- rtmp_do, /* do_it */
- rtmp_done, /* done */
- ZERO_NULL, /* do_more */
- rtmp_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_RTMP, /* defport */
- CURLPROTO_RTMPE, /* protocol */
- CURLPROTO_RTMPE, /* family */
- PROTOPT_NONE /* flags */
-};
-
-const struct Curl_handler Curl_handler_rtmpte = {
- "rtmpte", /* scheme */
- rtmp_setup_connection, /* setup_connection */
- rtmp_do, /* do_it */
- rtmp_done, /* done */
- ZERO_NULL, /* do_more */
- rtmp_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_RTMPT, /* defport */
- CURLPROTO_RTMPTE, /* protocol */
- CURLPROTO_RTMPTE, /* family */
- PROTOPT_NONE /* flags */
-};
-
-const struct Curl_handler Curl_handler_rtmps = {
- "rtmps", /* scheme */
- rtmp_setup_connection, /* setup_connection */
- rtmp_do, /* do_it */
- rtmp_done, /* done */
- ZERO_NULL, /* do_more */
- rtmp_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_RTMPS, /* defport */
- CURLPROTO_RTMPS, /* protocol */
- CURLPROTO_RTMP, /* family */
- PROTOPT_NONE /* flags */
-};
-
-const struct Curl_handler Curl_handler_rtmpts = {
- "rtmpts", /* scheme */
- rtmp_setup_connection, /* setup_connection */
- rtmp_do, /* do_it */
- rtmp_done, /* done */
- ZERO_NULL, /* do_more */
- rtmp_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_RTMPS, /* defport */
- CURLPROTO_RTMPTS, /* protocol */
- CURLPROTO_RTMPT, /* family */
- PROTOPT_NONE /* flags */
-};
-
static void rtmp_conn_dtor(void *key, size_t klen, void *entry)
{
RTMP *r = entry;
@@ -383,4 +221,106 @@
suff);
}
+/*
+ * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu/
+ */
+
+static const struct Curl_protocol Curl_protocol_rtmp = {
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_pollset */
+ ZERO_NULL, /* doing_pollset */
+ ZERO_NULL, /* domore_pollset */
+ ZERO_NULL, /* perform_pollset */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* write_resp */
+ ZERO_NULL, /* write_resp_hd */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
+};
+
#endif /* USE_LIBRTMP */
+
+const struct Curl_scheme Curl_scheme_rtmp = {
+ "rtmp", /* scheme */
+#ifndef USE_LIBRTMP
+ ZERO_NULL,
+#else
+ &Curl_protocol_rtmp,
+#endif
+ CURLPROTO_RTMP, /* protocol */
+ CURLPROTO_RTMP, /* family */
+ PROTOPT_NONE, /* flags */
+ PORT_RTMP, /* defport */
+};
+
+const struct Curl_scheme Curl_scheme_rtmpt = {
+ "rtmpt", /* scheme */
+#ifndef USE_LIBRTMP
+ ZERO_NULL,
+#else
+ &Curl_protocol_rtmp,
+#endif
+ CURLPROTO_RTMPT, /* protocol */
+ CURLPROTO_RTMPT, /* family */
+ PROTOPT_NONE, /* flags */
+ PORT_RTMPT, /* defport */
+};
+
+const struct Curl_scheme Curl_scheme_rtmpe = {
+ "rtmpe", /* scheme */
+#ifndef USE_LIBRTMP
+ ZERO_NULL,
+#else
+ &Curl_protocol_rtmp,
+#endif
+ CURLPROTO_RTMPE, /* protocol */
+ CURLPROTO_RTMPE, /* family */
+ PROTOPT_NONE, /* flags */
+ PORT_RTMP, /* defport */
+};
+
+const struct Curl_scheme Curl_scheme_rtmpte = {
+ "rtmpte", /* scheme */
+#ifndef USE_LIBRTMP
+ ZERO_NULL,
+#else
+ &Curl_protocol_rtmp,
+#endif
+ CURLPROTO_RTMPTE, /* protocol */
+ CURLPROTO_RTMPTE, /* family */
+ PROTOPT_NONE, /* flags */
+ PORT_RTMPT, /* defport */
+};
+
+const struct Curl_scheme Curl_scheme_rtmps = {
+ "rtmps", /* scheme */
+#ifndef USE_LIBRTMP
+ ZERO_NULL,
+#else
+ &Curl_protocol_rtmp,
+#endif
+ CURLPROTO_RTMPS, /* protocol */
+ CURLPROTO_RTMP, /* family */
+ PROTOPT_NONE, /* flags */
+ PORT_RTMPS, /* defport */
+};
+
+const struct Curl_scheme Curl_scheme_rtmpts = {
+ "rtmpts", /* scheme */
+#ifndef USE_LIBRTMP
+ ZERO_NULL,
+#else
+ &Curl_protocol_rtmp,
+#endif
+ CURLPROTO_RTMPTS, /* protocol */
+ CURLPROTO_RTMPT, /* family */
+ PROTOPT_NONE, /* flags */
+ PORT_RTMPS, /* defport */
+};
diff --git a/Utilities/cmcurl/lib/curl_rtmp.h b/Utilities/cmcurl/lib/curl_rtmp.h
index 339d3a4..e57d20c 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.h
+++ b/Utilities/cmcurl/lib/curl_rtmp.h
@@ -23,14 +23,13 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+extern const struct Curl_scheme Curl_scheme_rtmp;
+extern const struct Curl_scheme Curl_scheme_rtmpt;
+extern const struct Curl_scheme Curl_scheme_rtmpe;
+extern const struct Curl_scheme Curl_scheme_rtmpte;
+extern const struct Curl_scheme Curl_scheme_rtmps;
+extern const struct Curl_scheme Curl_scheme_rtmpts;
#ifdef USE_LIBRTMP
-extern const struct Curl_handler Curl_handler_rtmp;
-extern const struct Curl_handler Curl_handler_rtmpt;
-extern const struct Curl_handler Curl_handler_rtmpe;
-extern const struct Curl_handler Curl_handler_rtmpte;
-extern const struct Curl_handler Curl_handler_rtmps;
-extern const struct Curl_handler Curl_handler_rtmpts;
-
void Curl_rtmp_version(char *version, size_t len);
#endif
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 123c1c1..b2eb1fe 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -183,9 +183,9 @@
static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
saslstate newstate)
{
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
/* for debug purposes */
- static const char * const names[]={
+ static const char * const names[] = {
"STOP",
"PLAIN",
"LOGIN",
@@ -227,13 +227,14 @@
result = sasl->params->getmessage(data, out);
if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) {
- unsigned char *msg;
- size_t msglen;
const char *serverdata = Curl_bufref_ptr(out);
if(!*serverdata || *serverdata == '=')
Curl_bufref_set(out, NULL, 0, NULL);
else {
+ unsigned char *msg;
+ size_t msglen;
+
result = curlx_base64_decode(serverdata, &msg, &msglen);
if(!result)
Curl_bufref_set(out, msg, msglen, curl_free);
@@ -332,8 +333,8 @@
Curl_auth_create_gssapi_user_message(data, sctx->conn->user,
sctx->conn->passwd,
service, sctx->conn->host.name,
- sctx->sasl->mutual_auth, NULL,
- krb5, &sctx->resp);
+ (bool)sctx->sasl->mutual_auth,
+ NULL, krb5, &sctx->resp);
}
return TRUE;
}
@@ -711,9 +712,9 @@
struct kerberos5data *krb5 = Curl_auth_krb5_get(conn);
result = !krb5 ? CURLE_OUT_OF_MEMORY :
Curl_auth_create_gssapi_user_message(data, conn->user, conn->passwd,
- service, conn->host.name,
- sasl->mutual_auth, NULL,
- krb5, &resp);
+ service, conn->host.name,
+ (bool)sasl->mutual_auth, NULL,
+ krb5, &resp);
newstate = SASL_GSSAPI_TOKEN;
break;
}
@@ -728,7 +729,7 @@
message */
result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
NULL, NULL,
- sasl->mutual_auth,
+ (bool)sasl->mutual_auth,
&serverdata,
krb5, &resp);
newstate = SASL_GSSAPI_NO_DATA;
@@ -801,7 +802,7 @@
sasl->curmech = NULL;
/* Start an alternative SASL authentication */
- return Curl_sasl_start(sasl, data, sasl->force_ir, progress);
+ return Curl_sasl_start(sasl, data, (bool)sasl->force_ir, progress);
default:
failf(data, "Unsupported SASL authentication mechanism");
result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
@@ -834,7 +835,7 @@
return result;
}
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
static void sasl_unchosen(struct Curl_easy *data, unsigned short mech,
unsigned short enabledmechs,
bool built_in, bool platform,
@@ -865,11 +866,11 @@
infof(data, "SASL: %s is missing username", mname);
}
}
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* CURLVERBOSE */
CURLcode Curl_sasl_is_blocked(struct SASL *sasl, struct Curl_easy *data)
{
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
#ifdef USE_KERBEROS5
#define CURL_SASL_KERBEROS5 TRUE
#else
@@ -924,7 +925,7 @@
data->set.str[STRING_BEARER] ?
NULL : "CURLOPT_XOAUTH2_BEARER");
}
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* CURLVERBOSE */
(void)sasl;
(void)data;
return CURLE_LOGIN_DENIED;
diff --git a/Utilities/cmcurl/lib/curl_sasl.h b/Utilities/cmcurl/lib/curl_sasl.h
index 8432d26..8a97f52 100644
--- a/Utilities/cmcurl/lib/curl_sasl.h
+++ b/Utilities/cmcurl/lib/curl_sasl.h
@@ -129,7 +129,7 @@
/* This is used to test whether the line starts with the given mechanism */
#define sasl_mech_equal(line, wordlen, mech) \
- (wordlen == (sizeof(mech) - 1) / sizeof(char) && \
+ ((wordlen) == (sizeof(mech) - 1) / sizeof(char) && \
!memcmp(line, mech, wordlen))
/* Convert a mechanism name to a token */
@@ -147,11 +147,11 @@
/* Check if we have enough auth data and capabilities to authenticate */
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data);
-/* Calculate the required login details for SASL authentication */
+/* Calculate the required login details for SASL authentication */
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
bool force_ir, saslprogress *progress);
-/* Continue an SASL authentication */
+/* Continue an SASL authentication */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
int code, saslprogress *progress);
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index b976838..90d2ff7 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -89,12 +89,8 @@
#ifdef _MSC_VER
/* Disable Visual Studio warnings: 4127 "conditional expression is constant" */
#pragma warning(disable:4127)
-/* Avoid VS2005 and upper complaining about portable C functions. */
-#ifndef _CRT_NONSTDC_NO_DEPRECATE /* mingw-w64 v2+. MS SDK ~10+/~VS2017+. */
-#define _CRT_NONSTDC_NO_DEPRECATE /* for close(), fileno(), unlink(), etc. */
-#endif
#ifndef _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_WARNINGS /* for getenv(), tests: sscanf() */
+#define _CRT_SECURE_NO_WARNINGS /* for getenv(), sscanf() */
#endif
#endif /* _MSC_VER */
@@ -110,6 +106,7 @@
# ifndef NOGDI
# define NOGDI
# endif
+
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
@@ -120,6 +117,12 @@
# define CURL_WINDOWS_UWP
# endif
# endif
+
+/* Mandatory to define SECURITY_WIN32 or SECURITY_KERNEL to indicating who is
+ compiling the code. */
+#undef SECURITY_KERNEL
+#undef SECURITY_WIN32
+#define SECURITY_WIN32 /* for <sspi.h> */
#endif
/* Compatibility */
@@ -154,16 +157,24 @@
# include "config-os400.h"
#endif
-#ifdef __PLAN9__
-# include "config-plan9.h"
-#endif
-
#endif /* HAVE_CONFIG_H */
#if defined(_MSC_VER)
# pragma warning(push,1)
#endif
+#ifdef _WIN32
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
+# error The minimum build target is Windows Vista (0x0600)
+# endif
+
+# if !defined(CURL_WINDOWS_UWP) && (defined(_MSC_VER) || defined(__MINGW32__))
+# ifndef HAVE_IF_NAMETOINDEX
+# define HAVE_IF_NAMETOINDEX
+# endif
+# endif
+#endif
+
/* ================================================================ */
/* Definition of preprocessor macros/symbols which modify compiler */
/* behavior or generated code characteristics must be done here, */
@@ -263,6 +274,9 @@
# ifndef CURL_DISABLE_TFTP
# define CURL_DISABLE_TFTP
# endif
+# ifndef CURL_DISABLE_WEBSOCKETS
+# define CURL_DISABLE_WEBSOCKETS
+# endif
#endif
/*
@@ -276,16 +290,39 @@
* When HTTP is disabled, disable HTTP-only features
*/
#ifdef CURL_DISABLE_HTTP
-# define CURL_DISABLE_ALTSVC 1
-# define CURL_DISABLE_COOKIES 1
-# define CURL_DISABLE_BASIC_AUTH 1
-# define CURL_DISABLE_BEARER_AUTH 1
-# define CURL_DISABLE_AWS 1
-# define CURL_DISABLE_DOH 1
-# define CURL_DISABLE_FORM_API 1
-# define CURL_DISABLE_HEADERS_API 1
-# define CURL_DISABLE_HSTS 1
-# define CURL_DISABLE_HTTP_AUTH 1
+# ifndef CURL_DISABLE_ALTSVC
+# define CURL_DISABLE_ALTSVC
+# endif
+# ifndef CURL_DISABLE_COOKIES
+# define CURL_DISABLE_COOKIES
+# endif
+# ifndef CURL_DISABLE_BASIC_AUTH
+# define CURL_DISABLE_BASIC_AUTH
+# endif
+# ifndef CURL_DISABLE_BEARER_AUTH
+# define CURL_DISABLE_BEARER_AUTH
+# endif
+# ifndef CURL_DISABLE_AWS
+# define CURL_DISABLE_AWS
+# endif
+# ifndef CURL_DISABLE_DOH
+# define CURL_DISABLE_DOH
+# endif
+# ifndef CURL_DISABLE_FORM_API
+# define CURL_DISABLE_FORM_API
+# endif
+# ifndef CURL_DISABLE_HEADERS_API
+# define CURL_DISABLE_HEADERS_API
+# endif
+# ifndef CURL_DISABLE_HSTS
+# define CURL_DISABLE_HSTS
+# endif
+# ifndef CURL_DISABLE_HTTP_AUTH
+# define CURL_DISABLE_HTTP_AUTH
+# endif
+# ifndef CURL_DISABLE_WEBSOCKETS
+# define CURL_DISABLE_WEBSOCKETS /* no WebSockets without HTTP present */
+# endif
#endif
/* ================================================================ */
@@ -449,6 +486,10 @@
#define USE_EVENTFD
#endif
+#ifdef SO_NOSIGPIPE
+#define USE_SO_NOSIGPIPE
+#endif
+
#include <stdio.h>
#include <assert.h>
@@ -462,8 +503,19 @@
#include <curl/stdcheaders.h>
#endif
-#if defined(HAVE_STDINT_H) || defined(USE_WOLFSSL)
#include <stdint.h>
+#define HAVE_UINTPTR_T /* assume uintptr_t is provided by stdint.h */
+
+#ifdef __DJGPP__
+/* By default, DJGPP provides this type as a version of 'unsigned long' which
+ forces us to use a define use it in printf() format strings without
+ warnings. long and int are both 32 bits for this platform. */
+#define uint32_t unsigned int
+#endif
+
+/* Disable uintptr_t for targets known to miss it from stdint.h */
+#ifdef __OS400__
+#undef HAVE_UINTPTR_T
#endif
#include <limits.h>
@@ -486,26 +538,19 @@
# include <sys/types.h>
# include <sys/stat.h>
/* Large file (>2Gb) support using Win32 functions. */
-# undef lseek
-# define lseek(fdes, offset, whence) _lseeki64(fdes, offset, whence)
-# undef fstat
-# define fstat(fdes, stp) _fstati64(fdes, stp)
-# define struct_stat struct _stati64
-# define LSEEK_ERROR (__int64)-1
+# define curl_lseek _lseeki64
+# define LSEEK_ERROR ((__int64)-1)
#elif defined(__DJGPP__)
/* Requires DJGPP 2.04 */
# include <unistd.h>
-# undef lseek
-# define lseek(fdes, offset, whence) llseek(fdes, offset, whence)
-# define LSEEK_ERROR (offset_t)-1
-#endif
-
-#ifndef struct_stat
-#define struct_stat struct stat
-#endif
-
-#ifndef LSEEK_ERROR
-#define LSEEK_ERROR (off_t)-1
+# define curl_lseek llseek
+# define LSEEK_ERROR ((offset_t)-1)
+#elif defined(__AMIGA__)
+# define curl_lseek(fd, offset, whence) lseek(fd, (off_t)(offset), whence)
+# define LSEEK_ERROR ((off_t)-1)
+#else
+# define curl_lseek lseek
+# define LSEEK_ERROR ((off_t)-1)
#endif
#ifndef SIZEOF_TIME_T
@@ -515,7 +560,7 @@
#ifndef SIZEOF_CURL_SOCKET_T
/* configure and cmake check and set the define */
-# ifdef _WIN64
+# if defined(USE_WINSOCK) && defined(_WIN64)
# define SIZEOF_CURL_SOCKET_T 8
# else
/* default guess */
@@ -524,12 +569,12 @@
#endif
#if SIZEOF_CURL_SOCKET_T < 8
-#ifdef _WIN32
+#ifdef USE_WINSOCK
# define FMT_SOCKET_T "u"
#else
# define FMT_SOCKET_T "d"
#endif
-#elif defined(_WIN32)
+#elif defined(USE_WINSOCK)
# define FMT_SOCKET_T "zu"
#else
# define FMT_SOCKET_T "qd"
@@ -678,7 +723,7 @@
#elif defined(USE_ARES)
# define CURLRES_ASYNCH
# define CURLRES_ARES
-/* now undef the stock libc functions just to avoid them being used */
+/* now undef the stock libc functions to avoid them being used */
# undef HAVE_GETADDRINFO
# undef HAVE_FREEADDRINFO
#else
@@ -704,14 +749,9 @@
#endif
#if defined(USE_OPENSSL) && defined(USE_WOLFSSL)
-# include <wolfssl/version.h>
-# if LIBWOLFSSL_VERSION_HEX >= 0x05007006
-# ifndef OPENSSL_COEXIST
-# define OPENSSL_COEXIST
-# endif
-# else
-# error "OpenSSL can only coexist with wolfSSL v5.7.6 or upper"
-# endif
+#ifndef OPENSSL_COEXIST
+#define OPENSSL_COEXIST
+#endif
#endif
#if defined(USE_WOLFSSL) && defined(USE_GNUTLS)
@@ -783,27 +823,357 @@
(defined(__clang__) && __clang_major__ >= 10)
# define FALLTHROUGH() __attribute__((fallthrough))
#else
-# define FALLTHROUGH() do {} while (0)
+# define FALLTHROUGH() do {} while(0)
#endif
#endif
/*
- * Include macros and defines that should only be processed once.
+ * Inclusion of common header files.
*/
-#ifndef HEADER_CURL_SETUP_ONCE_H
-#include "curl_setup_once.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
#endif
+#include <sys/stat.h>
+
+#if !defined(_WIN32) || defined(__MINGW32__)
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T)
+#include <stdbool.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Macro to strip 'const' without triggering a compiler warning.
+ Use it for APIs that do not or cannot support the const qualifier. */
+#ifdef HAVE_UINTPTR_T
+#define CURL_UNCONST(p) ((void *)(uintptr_t)(const void *)(p))
+#else
+#define CURL_UNCONST(p) ((void *)(p)) /* Fall back to simple cast */
+#endif
+
+#ifdef USE_SCHANNEL
+/* Must set this before <schannel.h> is included directly or indirectly by
+ another Windows header. */
+# define SCHANNEL_USE_BLACKLISTS /* for SCH_CREDENTIALS */
+# include <subauth.h> /* for [P]UNICODE_STRING in SCH_CREDENTIALS */
+#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef _APP32_64BIT_OFF_T
+# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
+# undef _APP32_64BIT_OFF_T
+# else
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+#ifndef _WIN32
+#include <sys/socket.h> /* also for MSG_NOSIGNAL */
+#endif
+
+#include "functypes.h"
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef OLD_APP32_64BIT_OFF_T
+# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+/*
+ * Definition of timeval struct for platforms that do not have it.
+ */
+#ifndef HAVE_STRUCT_TIMEVAL
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+#endif
+
+/*
+ * If we have the MSG_NOSIGNAL define, make sure we use
+ * it as the fourth argument of function send()
+ */
+#ifdef MSG_NOSIGNAL
+#define SEND_4TH_ARG MSG_NOSIGNAL
+#else
+#define SEND_4TH_ARG 0
+#endif
+
+#ifdef __minix
+/* Minix does not support recv on TCP sockets */
+#define sread(x, y, z) (ssize_t)read((RECV_TYPE_ARG1)(x), \
+ (RECV_TYPE_ARG2)(y), \
+ (RECV_TYPE_ARG3)(z))
+
+#elif defined(HAVE_RECV)
+/*
+ * The definitions for the return type and arguments types
+ * of functions recv() and send() belong and come from the
+ * configuration file. Do not define them in any other place.
+ *
+ * HAVE_RECV is defined if you have a function named recv()
+ * which is used to read incoming data from sockets. If your
+ * function has another name then do not define HAVE_RECV.
+ *
+ * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
+ * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
+ * be defined.
+ *
+ * HAVE_SEND is defined if you have a function named send()
+ * which is used to write outgoing data on a connected socket.
+ * If yours has another name then do not define HAVE_SEND.
+ *
+ * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_TYPE_ARG2,
+ * SEND_TYPE_ARG3, SEND_TYPE_ARG4 and SEND_TYPE_RETV must also
+ * be defined. SEND_NONCONST_ARG2 must also be defined if ARG2
+ * does not accept const.
+ */
+
+#define sread(x, y, z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
+ (RECV_TYPE_ARG2)(y), \
+ (RECV_TYPE_ARG3)(z), \
+ (RECV_TYPE_ARG4)(0))
+#else /* HAVE_RECV */
+#ifndef sread
+#error "Missing definition of macro sread!"
+#endif
+#endif /* HAVE_RECV */
+
+#ifdef __minix
+/* Minix does not support send on TCP sockets */
+#define swrite(x, y, z) (ssize_t)write((SEND_TYPE_ARG1)(x), \
+ (SEND_TYPE_ARG2)CURL_UNCONST(y), \
+ (SEND_TYPE_ARG3)(z))
+#elif defined(HAVE_SEND)
+#ifdef SEND_NONCONST_ARG2
+#define swrite(x, y, z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
+ (SEND_TYPE_ARG2)CURL_UNCONST(y), \
+ (SEND_TYPE_ARG3)(z), \
+ (SEND_TYPE_ARG4)(SEND_4TH_ARG))
+#else
+#define swrite(x, y, z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
+ (const SEND_TYPE_ARG2)(y), \
+ (SEND_TYPE_ARG3)(z), \
+ (SEND_TYPE_ARG4)(SEND_4TH_ARG))
+#endif /* SEND_NONCONST_ARG2 */
+#else /* HAVE_SEND */
+#ifndef swrite
+#error "Missing definition of macro swrite!"
+#endif
+#endif /* HAVE_SEND */
+
+/*
+ * Function-like macro definition used to close a socket.
+ */
+#ifdef HAVE_CLOSESOCKET
+# define CURL_SCLOSE(x) closesocket(x)
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define CURL_SCLOSE(x) CloseSocket(x)
+#elif defined(MSDOS) /* Watt-32 */
+# define CURL_SCLOSE(x) close_s(x)
+#elif defined(USE_LWIPSOCK)
+# define CURL_SCLOSE(x) lwip_close(x)
+#else
+# define CURL_SCLOSE(x) close(x)
+#endif
+
+/*
+ * Stack-independent version of fcntl() on sockets:
+ */
+#ifdef USE_LWIPSOCK
+# define sfcntl lwip_fcntl
+#else
+# define sfcntl fcntl
+#endif
+
+/*
+ * 'bool' stuff compatible with HP-UX headers.
+ */
+#if defined(__hpux) && !defined(HAVE_BOOL_T)
+ typedef int bool;
+# define false 0
+# define true 1
+# define HAVE_BOOL_T
+#endif
+
+/*
+ * 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
+ * On non-C99 platforms there is no bool, so define an enum for that.
+ * On C99 platforms 'false' and 'true' also exist. Enum uses a
+ * global namespace though, so use bool_false and bool_true.
+ */
+#ifndef HAVE_BOOL_T
+ typedef enum {
+ bool_false = 0,
+ bool_true = 1
+ } bool;
+
+/*
+ * Use a define to let 'true' and 'false' use those enums. There
+ * are currently no use of true and false in libcurl proper, but
+ * there are some in the examples. This will cater for any later
+ * code happening to use true and false.
+ */
+# define false bool_false
+# define true bool_true
+# define HAVE_BOOL_T
+#endif
+
+/* the type we use for storing a single boolean bit */
+typedef unsigned int curl_bit;
+#define BIT(x) curl_bit x:1
+
+/*
+ * Redefine TRUE and FALSE too, to catch current use. With this
+ * change, 'bool found = 1' will give a warning on MIPSPro, but
+ * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro,
+ * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too.
+ */
+#ifndef TRUE
+#define TRUE true
+#endif
+#ifndef FALSE
+#define FALSE false
+#endif
+
+#include "curl_ctype.h"
+
+/*
+ * Macro used to include code only in debug builds.
+ */
+#ifdef DEBUGBUILD
+#define DEBUGF(x) x
+#else
+#define DEBUGF(x) do {} while(0)
+#endif
+
+/*
+ * Macro used to include assertion code only in debug builds.
+ */
+#undef DEBUGASSERT
+#ifdef DEBUGBUILD
+#ifdef CURL_DEBUGASSERT
+/* External assertion handler for custom integrations */
+#define DEBUGASSERT(x) CURL_DEBUGASSERT(x)
+#else
+#define DEBUGASSERT(x) assert(x)
+#endif
+#else
+#define DEBUGASSERT(x) do {} while(0)
+#endif
+
+/*
+ * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+#ifdef USE_WINSOCK
+#define SOCKERRNO ((int)WSAGetLastError())
+#define SET_SOCKERRNO(x) WSASetLastError((int)(x))
+#else
+#define SOCKERRNO errno
+#define SET_SOCKERRNO(x) (errno = (x))
+#endif
+
+/*
+ * Portable error number symbolic names defined to Winsock error codes.
+ */
+#ifdef USE_WINSOCK
+#define SOCKEACCES WSAEACCES
+#define SOCKEADDRINUSE WSAEADDRINUSE
+#define SOCKEADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define SOCKEAFNOSUPPORT WSAEAFNOSUPPORT
+#define SOCKEBADF WSAEBADF
+#define SOCKECONNREFUSED WSAECONNREFUSED
+#define SOCKECONNRESET WSAECONNRESET
+#define SOCKEINPROGRESS WSAEINPROGRESS
+#define SOCKEINTR WSAEINTR
+#define SOCKEINVAL WSAEINVAL
+#define SOCKEISCONN WSAEISCONN
+#define SOCKEMSGSIZE WSAEMSGSIZE
+/* Use literal value to work around clang-tidy <=20 misreporting
+ 'readability-uppercase-literal-suffix' with mingw-w64 headers */
+#define SOCKENOMEM 8L /* WSA_NOT_ENOUGH_MEMORY */
+#define SOCKETIMEDOUT WSAETIMEDOUT
+#define SOCKEWOULDBLOCK WSAEWOULDBLOCK
+#else
+#define SOCKEACCES EACCES
+#define SOCKEADDRINUSE EADDRINUSE
+#define SOCKEADDRNOTAVAIL EADDRNOTAVAIL
+#define SOCKEAFNOSUPPORT EAFNOSUPPORT
+#define SOCKEBADF EBADF
+#define SOCKECONNREFUSED ECONNREFUSED
+#define SOCKECONNRESET ECONNRESET
+#define SOCKEINPROGRESS EINPROGRESS
+#define SOCKEINTR EINTR
+#define SOCKEINVAL EINVAL
+#define SOCKEISCONN EISCONN
+#define SOCKEMSGSIZE EMSGSIZE
+#define SOCKENOMEM ENOMEM
+#ifdef ETIMEDOUT
+#define SOCKETIMEDOUT ETIMEDOUT
+#endif
+#define SOCKEWOULDBLOCK EWOULDBLOCK
+#endif
+
+/*
+ * Macro argv_item_t hides platform details to code using it.
+ */
+#ifdef __VMS
+#define argv_item_t __char_ptr32
+#elif defined(_UNICODE)
+#define argv_item_t wchar_t *
+#else
+#define argv_item_t char *
+#endif
+
+/*
+ * We use this ZERO_NULL to avoid picky compiler warnings,
+ * when assigning a NULL pointer to a function pointer var.
+ */
+#define ZERO_NULL 0
+
/*
* Macros and functions to safely suppress warnings
*/
#include "curlx/warnless.h"
#ifdef _WIN32
-# undef read
+# undef read
# define read(fd, buf, count) (ssize_t)_read(fd, buf, curlx_uztoui(count))
-# undef write
+# undef write
# define write(fd, buf, count) (ssize_t)_write(fd, buf, curlx_uztoui(count))
+/* Avoid VS2005+ _CRT_NONSTDC_NO_DEPRECATE warnings about non-portable funcs */
+# undef fileno
+# define fileno(fh) _fileno(fh)
+# undef unlink
+# define unlink(fn) _unlink(fn)
+# undef isatty
+# define isatty(fd) _isatty(fd)
#endif
/*
@@ -860,12 +1230,23 @@
/* Since O_BINARY is used in bitmasks, setting it to zero makes it usable in
source code but yet it does not ruin anything */
-#ifdef O_BINARY
+#ifdef _O_BINARY /* for _WIN32 || MSDOS */
+#define CURL_O_BINARY _O_BINARY
+#elif defined(O_BINARY) /* __CYGWIN__ */
#define CURL_O_BINARY O_BINARY
#else
#define CURL_O_BINARY 0
#endif
+/* Requires io.h when available */
+#ifdef MSDOS
+#define CURL_BINMODE(stream) (void)setmode(fileno(stream), CURL_O_BINARY)
+#elif defined(_WIN32) || defined(__CYGWIN__)
+#define CURL_BINMODE(stream) (void)_setmode(fileno(stream), CURL_O_BINARY)
+#else
+#define CURL_BINMODE(stream) (void)(stream)
+#endif
+
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
@@ -891,7 +1272,7 @@
/* for systems that do not detect this in configure */
#ifndef CURL_SA_FAMILY_T
-# ifdef _WIN32
+# ifdef USE_WINSOCK
# define CURL_SA_FAMILY_T ADDRESS_FAMILY
# elif defined(HAVE_SA_FAMILY_T)
# define CURL_SA_FAMILY_T sa_family_t
@@ -953,7 +1334,11 @@
#include <curl/curl.h> /* for CURL_EXTERN, curl_socket_t, mprintf.h */
-#ifdef CURLDEBUG
+#ifdef DEBUGBUILD
+#define CURL_MEMDEBUG
+#endif
+
+#ifdef CURL_MEMDEBUG
#ifdef __clang__
# define ALLOC_FUNC __attribute__((__malloc__))
# if __clang_major__ >= 4
@@ -1036,10 +1421,10 @@
#define CURL_FREEADDRINFO(data) \
curl_dbg_freeaddrinfo(data, __LINE__, __FILE__)
#define CURL_SOCKET(domain, type, protocol) \
- curl_dbg_socket((int)domain, type, protocol, __LINE__, __FILE__)
+ curl_dbg_socket((int)(domain), type, protocol, __LINE__, __FILE__)
#ifdef HAVE_SOCKETPAIR
#define CURL_SOCKETPAIR(domain, type, protocol, socket_vector) \
- curl_dbg_socketpair((int)domain, type, protocol, socket_vector, \
+ curl_dbg_socketpair((int)(domain), type, protocol, socket_vector, \
__LINE__, __FILE__)
#endif
#define CURL_ACCEPT(sock, addr, len) \
@@ -1049,7 +1434,7 @@
curl_dbg_accept4(sock, addr, len, flags, __LINE__, __FILE__)
#endif
-#else /* !CURLDEBUG */
+#else /* !CURL_MEMDEBUG */
#define sclose(x) CURL_SCLOSE(x)
#define fake_sclose(x) Curl_nop_stmt
@@ -1065,11 +1450,17 @@
#define CURL_ACCEPT4 accept4
#endif
-#endif /* CURLDEBUG */
+#endif /* CURL_MEMDEBUG */
/* Allocator macros */
-#ifdef CURLDEBUG
+#ifdef _WIN32
+#define CURLX_STRDUP_LOW _strdup
+#else
+#define CURLX_STRDUP_LOW strdup
+#endif
+
+#ifdef CURL_MEMDEBUG
#define curlx_strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
#define curlx_malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__)
@@ -1083,39 +1474,35 @@
#ifdef UNICODE
#define curlx_tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
#else
-#define curlx_tcsdup(ptr) curlx_strdup(ptr)
+#define curlx_tcsdup curlx_strdup
#endif
#endif /* _WIN32 */
-#else /* !CURLDEBUG */
+#else /* !CURL_MEMDEBUG */
#ifdef BUILDING_LIBCURL
-#define curlx_strdup(ptr) Curl_cstrdup(ptr)
-#define curlx_malloc(size) Curl_cmalloc(size)
-#define curlx_calloc(nbelem, size) Curl_ccalloc(nbelem, size)
-#define curlx_realloc(ptr, size) Curl_crealloc(ptr, size)
-#define curlx_free(ptr) Curl_cfree(ptr)
+#define curlx_strdup Curl_cstrdup
+#define curlx_malloc Curl_cmalloc
+#define curlx_calloc Curl_ccalloc
+#define curlx_realloc Curl_crealloc
+#define curlx_free Curl_cfree
#else /* !BUILDING_LIBCURL */
-#ifdef _WIN32
-#define curlx_strdup(ptr) _strdup(ptr)
-#else
-#define curlx_strdup(ptr) strdup(ptr)
-#endif
-#define curlx_malloc(size) malloc(size)
-#define curlx_calloc(nbelem, size) calloc(nbelem, size)
-#define curlx_realloc(ptr, size) realloc(ptr, size)
-#define curlx_free(ptr) free(ptr)
+#define curlx_strdup CURLX_STRDUP_LOW
+#define curlx_malloc malloc
+#define curlx_calloc calloc
+#define curlx_realloc realloc
+#define curlx_free free
#endif /* BUILDING_LIBCURL */
#ifdef _WIN32
#ifdef UNICODE
-#define curlx_tcsdup(ptr) Curl_wcsdup(ptr)
+#define curlx_tcsdup curlx_wcsdup
#else
-#define curlx_tcsdup(ptr) curlx_strdup(ptr)
+#define curlx_tcsdup curlx_strdup
#endif
#endif /* _WIN32 */
-#endif /* CURLDEBUG */
+#endif /* CURL_MEMDEBUG */
/* Some versions of the Android NDK is missing the declaration */
#if defined(HAVE_GETPWUID_R) && \
@@ -1173,8 +1560,11 @@
#endif
#ifdef USE_OPENSSL
-/* OpenSSLv3 marks DES, MD5 and ENGINE functions deprecated but we have no
- replacements (yet) so tell the compiler to not warn for them. */
+/* OpenSSL 3 marks these functions deprecated but we have no replacements (yet)
+ so tell the compiler to not warn for them:
+ - DES_* (for NTLM), SSL_CTX_set_srp_* (for TLS-SRP)
+ - EVP_PKEY_get1_RSA, MD5_*, RSA_flags, RSA_free (auto-skipped for OpenSSL
+ built with no-deprecated) */
# define OPENSSL_SUPPRESS_DEPRECATED
# ifdef _WIN32
/* Silence LibreSSL warnings about wincrypt.h collision. Works in 3.8.2+ */
@@ -1206,4 +1596,20 @@
# define CURL_INLINE /* empty */
#endif
+/* Detect if compiler supports C99 variadic macros */
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+ defined(_MSC_VER)
+#define CURL_HAVE_MACRO_VARARG
+#endif
+
+#if !defined(CURL_HAVE_MACRO_VARARG) || \
+ (defined(CURL_HAVE_MACRO_VARARG) && !defined(CURL_DISABLE_VERBOSE_STRINGS))
+#define CURLVERBOSE
+#define VERBOSE(x) x
+#define NOVERBOSE(x) Curl_nop_stmt
+#else
+#define VERBOSE(x) Curl_nop_stmt
+#define NOVERBOSE(x) x
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
deleted file mode 100644
index 06ccc98..0000000
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ /dev/null
@@ -1,346 +0,0 @@
-#ifndef HEADER_CURL_SETUP_ONCE_H
-#define HEADER_CURL_SETUP_ONCE_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-/*
- * Inclusion of common header files.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-#include <errno.h>
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <sys/stat.h>
-
-#if !defined(_WIN32) || defined(__MINGW32__)
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T)
-#include <stdbool.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* Macro to strip 'const' without triggering a compiler warning.
- Use it for APIs that do not or cannot support the const qualifier. */
-#ifdef HAVE_STDINT_H
-# define CURL_UNCONST(p) ((void *)(uintptr_t)(const void *)(p))
-#else
-# define CURL_UNCONST(p) ((void *)(p)) /* Fall back to simple cast */
-#endif
-
-#ifdef USE_SCHANNEL
-/* Must set this before <schannel.h> is included directly or indirectly by
- another Windows header. */
-# define SCHANNEL_USE_BLACKLISTS 1
-#endif
-
-#ifdef __hpux
-# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
-# ifdef _APP32_64BIT_OFF_T
-# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
-# undef _APP32_64BIT_OFF_T
-# else
-# undef OLD_APP32_64BIT_OFF_T
-# endif
-# endif
-#endif
-
-#ifndef _WIN32
-#include <sys/socket.h>
-#endif
-
-#include "functypes.h"
-
-#ifdef __hpux
-# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
-# ifdef OLD_APP32_64BIT_OFF_T
-# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
-# undef OLD_APP32_64BIT_OFF_T
-# endif
-# endif
-#endif
-
-/*
- * Definition of timeval struct for platforms that do not have it.
- */
-#ifndef HAVE_STRUCT_TIMEVAL
-struct timeval {
- long tv_sec;
- long tv_usec;
-};
-#endif
-
-/*
- * If we have the MSG_NOSIGNAL define, make sure we use
- * it as the fourth argument of function send()
- */
-#ifdef HAVE_MSG_NOSIGNAL
-#define SEND_4TH_ARG MSG_NOSIGNAL
-#else
-#define SEND_4TH_ARG 0
-#endif
-
-#ifdef __minix
-/* Minix does not support recv on TCP sockets */
-#define sread(x, y, z) (ssize_t)read((RECV_TYPE_ARG1)(x), \
- (RECV_TYPE_ARG2)(y), \
- (RECV_TYPE_ARG3)(z))
-
-#elif defined(HAVE_RECV)
-/*
- * The definitions for the return type and arguments types
- * of functions recv() and send() belong and come from the
- * configuration file. Do not define them in any other place.
- *
- * HAVE_RECV is defined if you have a function named recv()
- * which is used to read incoming data from sockets. If your
- * function has another name then do not define HAVE_RECV.
- *
- * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
- * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
- * be defined.
- *
- * HAVE_SEND is defined if you have a function named send()
- * which is used to write outgoing data on a connected socket.
- * If yours has another name then do not define HAVE_SEND.
- *
- * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2,
- * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and
- * SEND_TYPE_RETV must also be defined.
- */
-
-#define sread(x, y, z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
- (RECV_TYPE_ARG2)(y), \
- (RECV_TYPE_ARG3)(z), \
- (RECV_TYPE_ARG4)(0))
-#else /* HAVE_RECV */
-#ifndef sread
-#error "Missing definition of macro sread!"
-#endif
-#endif /* HAVE_RECV */
-
-#ifdef __minix
-/* Minix does not support send on TCP sockets */
-#define swrite(x, y, z) (ssize_t)write((SEND_TYPE_ARG1)(x), \
- (SEND_TYPE_ARG2)CURL_UNCONST(y), \
- (SEND_TYPE_ARG3)(z))
-#elif defined(HAVE_SEND)
-#define swrite(x, y, z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
- (SEND_QUAL_ARG2 SEND_TYPE_ARG2)CURL_UNCONST(y), \
- (SEND_TYPE_ARG3)(z), \
- (SEND_TYPE_ARG4)(SEND_4TH_ARG))
-#else /* HAVE_SEND */
-#ifndef swrite
-#error "Missing definition of macro swrite!"
-#endif
-#endif /* HAVE_SEND */
-
-/*
- * Function-like macro definition used to close a socket.
- */
-#ifdef HAVE_CLOSESOCKET
-# define CURL_SCLOSE(x) closesocket(x)
-#elif defined(HAVE_CLOSESOCKET_CAMEL)
-# define CURL_SCLOSE(x) CloseSocket(x)
-#elif defined(MSDOS) /* Watt-32 */
-# define CURL_SCLOSE(x) close_s(x)
-#elif defined(USE_LWIPSOCK)
-# define CURL_SCLOSE(x) lwip_close(x)
-#else
-# define CURL_SCLOSE(x) close(x)
-#endif
-
-/*
- * Stack-independent version of fcntl() on sockets:
- */
-#ifdef USE_LWIPSOCK
-# define sfcntl lwip_fcntl
-#else
-# define sfcntl fcntl
-#endif
-
-/*
- * 'bool' stuff compatible with HP-UX headers.
- */
-#if defined(__hpux) && !defined(HAVE_BOOL_T)
- typedef int bool;
-# define false 0
-# define true 1
-# define HAVE_BOOL_T
-#endif
-
-/*
- * 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
- * On non-C99 platforms there is no bool, so define an enum for that.
- * On C99 platforms 'false' and 'true' also exist. Enum uses a
- * global namespace though, so use bool_false and bool_true.
- */
-#ifndef HAVE_BOOL_T
- typedef enum {
- bool_false = 0,
- bool_true = 1
- } bool;
-
-/*
- * Use a define to let 'true' and 'false' use those enums. There
- * are currently no use of true and false in libcurl proper, but
- * there are some in the examples. This will cater for any later
- * code happening to use true and false.
- */
-# define false bool_false
-# define true bool_true
-# define HAVE_BOOL_T
-#endif
-
-/* the type we use for storing a single boolean bit */
-#ifdef _MSC_VER
-typedef bool bit;
-#define BIT(x) bool x
-#else
-typedef unsigned int bit;
-#define BIT(x) bit x:1
-#endif
-
-/*
- * Redefine TRUE and FALSE too, to catch current use. With this
- * change, 'bool found = 1' will give a warning on MIPSPro, but
- * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro,
- * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too.
- */
-#ifndef TRUE
-#define TRUE true
-#endif
-#ifndef FALSE
-#define FALSE false
-#endif
-
-#include "curl_ctype.h"
-
-/*
- * Macro used to include code only in debug builds.
- */
-#ifdef DEBUGBUILD
-#define DEBUGF(x) x
-#else
-#define DEBUGF(x) do {} while(0)
-#endif
-
-/*
- * Macro used to include assertion code only in debug builds.
- */
-#undef DEBUGASSERT
-#ifdef DEBUGBUILD
-#define DEBUGASSERT(x) assert(x)
-#else
-#define DEBUGASSERT(x) do {} while(0)
-#endif
-
-/*
- * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
- * (or equivalent) on this platform to hide platform details to code using it.
- */
-#ifdef USE_WINSOCK
-#define SOCKERRNO ((int)WSAGetLastError())
-#define SET_SOCKERRNO(x) (WSASetLastError((int)(x)))
-#else
-#define SOCKERRNO (errno)
-#define SET_SOCKERRNO(x) (errno = (x))
-#endif
-
-/*
- * Portable error number symbolic names defined to Winsock error codes.
- */
-#ifdef USE_WINSOCK
-#define SOCKEACCES WSAEACCES
-#define SOCKEADDRINUSE WSAEADDRINUSE
-#define SOCKEADDRNOTAVAIL WSAEADDRNOTAVAIL
-#define SOCKEAFNOSUPPORT WSAEAFNOSUPPORT
-#define SOCKEBADF WSAEBADF
-#define SOCKECONNREFUSED WSAECONNREFUSED
-#define SOCKECONNRESET WSAECONNRESET
-#define SOCKEINPROGRESS WSAEINPROGRESS
-#define SOCKEINTR WSAEINTR
-#define SOCKEINVAL WSAEINVAL
-#define SOCKEISCONN WSAEISCONN
-#define SOCKEMSGSIZE WSAEMSGSIZE
-#define SOCKENOMEM WSA_NOT_ENOUGH_MEMORY
-#define SOCKETIMEDOUT WSAETIMEDOUT
-#define SOCKEWOULDBLOCK WSAEWOULDBLOCK
-#else
-#define SOCKEACCES EACCES
-#define SOCKEADDRINUSE EADDRINUSE
-#define SOCKEADDRNOTAVAIL EADDRNOTAVAIL
-#define SOCKEAFNOSUPPORT EAFNOSUPPORT
-#define SOCKEBADF EBADF
-#define SOCKECONNREFUSED ECONNREFUSED
-#define SOCKECONNRESET ECONNRESET
-#define SOCKEINPROGRESS EINPROGRESS
-#define SOCKEINTR EINTR
-#define SOCKEINVAL EINVAL
-#define SOCKEISCONN EISCONN
-#define SOCKEMSGSIZE EMSGSIZE
-#define SOCKENOMEM ENOMEM
-#ifdef ETIMEDOUT
-#define SOCKETIMEDOUT ETIMEDOUT
-#endif
-#define SOCKEWOULDBLOCK EWOULDBLOCK
-#endif
-
-/*
- * Macro argv_item_t hides platform details to code using it.
- */
-#ifdef __VMS
-#define argv_item_t __char_ptr32
-#elif defined(_UNICODE)
-#define argv_item_t wchar_t *
-#else
-#define argv_item_t char *
-#endif
-
-/*
- * We use this ZERO_NULL to avoid picky compiler warnings,
- * when assigning a NULL pointer to a function pointer var.
- */
-#define ZERO_NULL 0
-
-#endif /* HEADER_CURL_SETUP_ONCE_H */
diff --git a/Utilities/cmcurl/lib/curl_sha256.h b/Utilities/cmcurl/lib/curl_sha256.h
index 0aaa412..bc1512e 100644
--- a/Utilities/cmcurl/lib/curl_sha256.h
+++ b/Utilities/cmcurl/lib/curl_sha256.h
@@ -37,7 +37,7 @@
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
-CURLcode Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
+CURLcode Curl_sha256it(unsigned char *output, const unsigned char *input,
const size_t len);
#endif
diff --git a/Utilities/cmcurl/lib/curl_sha512_256.c b/Utilities/cmcurl/lib/curl_sha512_256.c
index 44ba9be..648e3e3 100644
--- a/Utilities/cmcurl/lib/curl_sha512_256.c
+++ b/Utilities/cmcurl/lib/curl_sha512_256.c
@@ -53,7 +53,7 @@
* The bug was fixed in NetBSD 9.4 release, NetBSD 10.0 release,
* NetBSD 10.99.11 development.
* It is safe to apply the workaround even if the bug is not present, as
- * the workaround just reduces performance slightly. */
+ * the workaround reduces performance slightly. */
# include <sys/param.h>
# if __NetBSD_Version__ < 904000000 || \
(__NetBSD_Version__ >= 999000000 && \
@@ -147,7 +147,7 @@
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
- # bytes
+ * bytes
* @return CURLE_OK if succeed,
* error code otherwise
*/
@@ -229,7 +229,7 @@
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
- # bytes
+ * bytes
* @return always CURLE_OK
*/
static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context)
@@ -452,14 +452,14 @@
/* Four 'Sigma' macro functions.
See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
-#define SIG0(x) \
- (Curl_rotr64((x), 28) ^ Curl_rotr64((x), 34) ^ Curl_rotr64((x), 39))
-#define SIG1(x) \
- (Curl_rotr64((x), 14) ^ Curl_rotr64((x), 18) ^ Curl_rotr64((x), 41))
-#define sig0(x) \
- (Curl_rotr64((x), 1) ^ Curl_rotr64((x), 8) ^ ((x) >> 7))
-#define sig1(x) \
- (Curl_rotr64((x), 19) ^ Curl_rotr64((x), 61) ^ ((x) >> 6))
+#define SIG0(x) \
+ (Curl_rotr64(x, 28) ^ Curl_rotr64(x, 34) ^ Curl_rotr64(x, 39))
+#define SIG1(x) \
+ (Curl_rotr64(x, 14) ^ Curl_rotr64(x, 18) ^ Curl_rotr64(x, 41))
+#define sig0(x) \
+ (Curl_rotr64(x, 1) ^ Curl_rotr64(x, 8) ^ ((x) >> 7))
+#define sig1(x) \
+ (Curl_rotr64(x, 19) ^ Curl_rotr64(x, 61) ^ ((x) >> 6))
if(1) {
unsigned int t;
@@ -520,8 +520,8 @@
used. */
#define SHA2STEP64(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) \
do { \
- (vD) += ((vH) += SIG1((vE)) + Sha512_Ch((vE), (vF), (vG)) + (kt) + (wt)); \
- (vH) += SIG0((vA)) + Sha512_Maj((vA), (vB), (vC)); \
+ (vD) += ((vH) += SIG1(vE) + Sha512_Ch(vE, vF, vG) + (kt) + (wt)); \
+ (vH) += SIG0(vA) + Sha512_Maj(vA, vB, vC); \
} while(0)
/* One step of SHA-512/256 computation with working variables rotation,
@@ -530,7 +530,7 @@
#define SHA2STEP64RV(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) \
do { \
uint64_t tmp_h_ = (vH); \
- SHA2STEP64((vA), (vB), (vC), (vD), (vE), (vF), (vG), tmp_h_, (kt), (wt)); \
+ SHA2STEP64(vA, vB, vC, vD, vE, vF, vG, tmp_h_, kt, wt); \
(vH) = (vG); \
(vG) = (vF); \
(vF) = (vE); \
@@ -546,7 +546,7 @@
Input data must be read in big-endian bytes order,
see FIPS PUB 180-4 section 3.1.2. */
#define SHA512_GET_W_FROM_DATA(buf, t) \
- CURL_GET_64BIT_BE(((const uint8_t *)(buf)) + (t) * SHA512_256_BYTES_IN_WORD)
+ CURL_GET_64BIT_BE((const uint8_t *)(buf) + ((t) * SHA512_256_BYTES_IN_WORD))
/* During first 16 steps, before making any calculation on each step, the
W element is read from the input data buffer as a big-endian value and
@@ -663,7 +663,7 @@
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
- # bytes
+ * bytes
* @return always CURLE_OK
*/
static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context)
@@ -727,10 +727,10 @@
/* Put in BE mode the leftmost part of the hash as the final digest.
See FIPS PUB 180-4 section 6.7. */
- CURL_PUT_64BIT_BE(digest + 0 * SHA512_256_BYTES_IN_WORD, ctx->H[0]);
- CURL_PUT_64BIT_BE(digest + 1 * SHA512_256_BYTES_IN_WORD, ctx->H[1]);
- CURL_PUT_64BIT_BE(digest + 2 * SHA512_256_BYTES_IN_WORD, ctx->H[2]);
- CURL_PUT_64BIT_BE(digest + 3 * SHA512_256_BYTES_IN_WORD, ctx->H[3]);
+ CURL_PUT_64BIT_BE(digest + (0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
+ CURL_PUT_64BIT_BE(digest + (1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
+ CURL_PUT_64BIT_BE(digest + (2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
+ CURL_PUT_64BIT_BE(digest + (3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
/* Erase potentially sensitive data. */
memset(ctx, 0, sizeof(struct Curl_sha512_256ctx));
diff --git a/Utilities/cmcurl/lib/curl_share.c b/Utilities/cmcurl/lib/curl_share.c
index 3ff2755..338727a 100644
--- a/Utilities/cmcurl/lib/curl_share.c
+++ b/Utilities/cmcurl/lib/curl_share.c
@@ -24,7 +24,6 @@
#include "curl_setup.h"
#include "urldata.h"
-#include "connect.h"
#include "curl_share.h"
#include "vtls/vtls.h"
#include "vtls/vtls_scache.h"
diff --git a/Utilities/cmcurl/lib/curl_share.h b/Utilities/cmcurl/lib/curl_share.h
index fcd9e32..5e3f82a 100644
--- a/Utilities/cmcurl/lib/curl_share.h
+++ b/Utilities/cmcurl/lib/curl_share.h
@@ -36,8 +36,8 @@
#define CURL_GOOD_SHARE 0x7e117a1e
#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
-#define CURL_SHARE_KEEP_CONNECT(s) \
- ((s) && ((s)->specifier & (1 << CURL_LOCK_DATA_CONNECT)))
+#define CURL_SHARE_KEEP_CONNECT(s) \
+ ((s) && ((s)->specifier & (1 << CURL_LOCK_DATA_CONNECT)))
/* this struct is libcurl-private, do not export details */
struct Curl_share {
@@ -65,13 +65,13 @@
#endif
};
-CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data,
- curl_lock_access);
-CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data);
+CURLSHcode Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
+ curl_lock_access accesstype);
+CURLSHcode Curl_share_unlock(struct Curl_easy *data, curl_lock_data type);
/* convenience macro to check if this handle is using a shared SSL spool */
-#define CURL_SHARE_ssl_scache(data) (data->share && \
- (data->share->specifier & \
+#define CURL_SHARE_ssl_scache(data) ((data)->share && \
+ ((data)->share->specifier & \
(1 << CURL_LOCK_DATA_SSL_SESSION)))
#endif /* HEADER_CURL_SHARE_H */
diff --git a/Utilities/cmcurl/lib/curl_sspi.c b/Utilities/cmcurl/lib/curl_sspi.c
index 6e27269..1d4cf92 100644
--- a/Utilities/cmcurl/lib/curl_sspi.c
+++ b/Utilities/cmcurl/lib/curl_sspi.c
@@ -26,7 +26,7 @@
#ifdef USE_WINDOWS_SSPI
#include "curl_sspi.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#include "curlx/multibyte.h"
/* Pointer to SSPI dispatch table */
diff --git a/Utilities/cmcurl/lib/curl_sspi.h b/Utilities/cmcurl/lib/curl_sspi.h
index 0fba510..3779d51 100644
--- a/Utilities/cmcurl/lib/curl_sspi.h
+++ b/Utilities/cmcurl/lib/curl_sspi.h
@@ -27,17 +27,7 @@
#ifdef USE_WINDOWS_SSPI
-/*
- * When including the following three headers, it is mandatory to define either
- * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code.
- */
-
-#undef SECURITY_WIN32
-#undef SECURITY_KERNEL
-#define SECURITY_WIN32 1
-#include <security.h>
#include <sspi.h>
-#include <rpc.h>
CURLcode Curl_sspi_global_init(void);
void Curl_sspi_global_cleanup(void);
@@ -56,7 +46,7 @@
/* Forward-declaration of global variables defined in curl_sspi.c */
extern PSecurityFunctionTable Curl_pSecFn;
-/* Provide some definitions missing in old headers */
+/* Provide Service Principal names as macros */
#define SP_NAME_DIGEST "WDigest"
#define SP_NAME_NTLM "NTLM"
#define SP_NAME_NEGOTIATE "Negotiate"
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index 241014c..0e067c0 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/lib/curl_threads.h
@@ -41,11 +41,7 @@
# define curl_mutex_t CRITICAL_SECTION
# define curl_thread_t HANDLE
# define curl_thread_t_null (HANDLE)0
-# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < _WIN32_WINNT_VISTA)
-# define Curl_mutex_init(m) InitializeCriticalSection(m)
-# else
-# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
-# endif
+# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
# define Curl_mutex_acquire(m) EnterCriticalSection(m)
# define Curl_mutex_release(m) LeaveCriticalSection(m)
# define Curl_mutex_destroy(m) DeleteCriticalSection(m)
diff --git a/Utilities/cmcurl/lib/curl_trc.c b/Utilities/cmcurl/lib/curl_trc.c
index 565d1b4..4b8734a 100644
--- a/Utilities/cmcurl/lib/curl_trc.c
+++ b/Utilities/cmcurl/lib/curl_trc.c
@@ -194,6 +194,36 @@
}
}
+void Curl_reset_fail(struct Curl_easy *data)
+{
+ if(data->set.errorbuffer)
+ data->set.errorbuffer[0] = 0;
+ data->state.errorbuf = FALSE;
+}
+
+#ifdef CURLVERBOSE
+struct curl_trc_feat Curl_trc_feat_multi = {
+ "MULTI",
+ CURL_LOG_LVL_NONE,
+};
+struct curl_trc_feat Curl_trc_feat_read = {
+ "READ",
+ CURL_LOG_LVL_NONE,
+};
+struct curl_trc_feat Curl_trc_feat_write = {
+ "WRITE",
+ CURL_LOG_LVL_NONE,
+};
+struct curl_trc_feat Curl_trc_feat_dns = {
+ "DNS",
+ CURL_LOG_LVL_NONE,
+};
+struct curl_trc_feat Curl_trc_feat_timer = {
+ "TIMER",
+ CURL_LOG_LVL_NONE,
+};
+#endif
+
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void trc_infof(struct Curl_easy *data,
@@ -248,27 +278,6 @@
}
}
-struct curl_trc_feat Curl_trc_feat_multi = {
- "MULTI",
- CURL_LOG_LVL_NONE,
-};
-struct curl_trc_feat Curl_trc_feat_read = {
- "READ",
- CURL_LOG_LVL_NONE,
-};
-struct curl_trc_feat Curl_trc_feat_write = {
- "WRITE",
- CURL_LOG_LVL_NONE,
-};
-struct curl_trc_feat Curl_trc_feat_dns = {
- "DNS",
- CURL_LOG_LVL_NONE,
-};
-struct curl_trc_feat Curl_trc_feat_timer = {
- "TIMER",
- CURL_LOG_LVL_NONE,
-};
-
static const char * const Curl_trc_timer_names[] = {
"100_TIMEOUT",
"ASYNC_NAME",
@@ -485,7 +494,7 @@
}
#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */
-#define TRC_CT_NONE (0)
+#define TRC_CT_NONE 0
#define TRC_CT_PROTOCOL (1 << 0)
#define TRC_CT_NETWORK (1 << 1)
#define TRC_CT_PROXY (1 << 2)
@@ -578,7 +587,7 @@
}
}
-static void trc_apply_level_by_category(int category, int lvl)
+static void trc_apply_level_by_category(unsigned int category, int lvl)
{
size_t i;
diff --git a/Utilities/cmcurl/lib/curl_trc.h b/Utilities/cmcurl/lib/curl_trc.h
index ff085d6..a82c945 100644
--- a/Utilities/cmcurl/lib/curl_trc.h
+++ b/Utilities/cmcurl/lib/curl_trc.h
@@ -61,13 +61,14 @@
#define failf Curl_failf
+/* In case failf() reported into the errorbuf, clear it again.
+ * This is used to clear information from happy eyeballing attempts
+ * when ultimately a successful attempt was made. */
+void Curl_reset_fail(struct Curl_easy *data);
+
#define CURL_LOG_LVL_NONE 0
#define CURL_LOG_LVL_INFO 1
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#define CURL_HAVE_C99
-#endif
-
/**
* Output an informational message when transfer's verbose logging is enabled.
*/
@@ -133,7 +134,7 @@
#define CURL_TRC_TIMER_is_verbose(data) \
Curl_trc_ft_is_verbose(data, &Curl_trc_feat_timer)
-#if defined(CURL_HAVE_C99) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if defined(CURL_HAVE_MACRO_VARARG) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
#define infof(data, ...) \
do { \
if(Curl_trc_is_verbose(data)) \
@@ -206,7 +207,70 @@
} while(0)
#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */
-#else /* CURL_HAVE_C99 */
+#elif defined(CURL_HAVE_MACRO_VARARG) && defined(CURL_DISABLE_VERBOSE_STRINGS)
+
+#define infof(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#define CURL_TRC_M(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#define CURL_TRC_CF(data, cf, ...) \
+ do { \
+ (void)(data); \
+ (void)(cf); \
+ } while(0)
+#define CURL_TRC_WRITE(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#define CURL_TRC_READ(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#define CURL_TRC_DNS(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#define CURL_TRC_TIMER(data, tid, ...) \
+ do { \
+ (void)(data); \
+ (void)(tid); \
+ } while(0)
+#ifndef CURL_DISABLE_FTP
+#define CURL_TRC_FTP(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#endif /* !CURL_DISABLE_FTP */
+#ifndef CURL_DISABLE_SMTP
+#define CURL_TRC_SMTP(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#endif /* !CURL_DISABLE_SMTP */
+#ifdef USE_SSL
+#define CURL_TRC_SSLS(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#endif /* USE_SSL */
+#ifdef USE_SSH
+#define CURL_TRC_SSH(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#endif /* USE_SSH */
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+#define CURL_TRC_WS(data, ...) \
+ do { \
+ (void)(data); \
+ } while(0)
+#endif
+
+#else /* !CURL_HAVE_MACRO_VARARG */
#define infof Curl_infof
#define CURL_TRC_M Curl_trc_multi
@@ -232,17 +296,18 @@
#define CURL_TRC_WS Curl_trc_ws
#endif
-#endif /* !CURL_HAVE_C99 */
+#endif /* CURL_HAVE_MACRO_VARARG */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-/* informational messages enabled */
-
+#ifdef CURLVERBOSE
extern struct curl_trc_feat Curl_trc_feat_multi;
extern struct curl_trc_feat Curl_trc_feat_read;
extern struct curl_trc_feat Curl_trc_feat_write;
extern struct curl_trc_feat Curl_trc_feat_dns;
extern struct curl_trc_feat Curl_trc_feat_timer;
+#endif
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+/* informational messages enabled */
#define Curl_trc_is_verbose(data) \
((data) && (data)->set.verbose && \
(!(data)->state.feat || \
@@ -262,13 +327,11 @@
#else /* CURL_DISABLE_VERBOSE_STRINGS */
/* All informational messages are not compiled in for size savings */
-
-#define Curl_trc_is_verbose(d) (FALSE)
-#define Curl_trc_cf_is_verbose(x, y) (FALSE)
-#define Curl_trc_ft_is_verbose(x, y) (FALSE)
+#define Curl_trc_is_verbose(d) FALSE
+#define Curl_trc_cf_is_verbose(x, y) FALSE
+#define Curl_trc_ft_is_verbose(x, y) FALSE
#define CURL_MSTATE_NAME(x) ((void)(x), "-")
#define CURL_TRC_EASY_TIMERS(x) Curl_nop_stmt
-
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
#endif /* HEADER_CURL_TRC_H */
diff --git a/Utilities/cmcurl/lib/curlx/base64.c b/Utilities/cmcurl/lib/curlx/base64.c
index 0e44eae..a7a6703 100644
--- a/Utilities/cmcurl/lib/curlx/base64.c
+++ b/Utilities/cmcurl/lib/curlx/base64.c
@@ -24,9 +24,9 @@
/* Base64 encoding/decoding */
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "base64.h"
+#include "curlx/base64.h"
/* ---- Base64 Encoding/Decoding Table --- */
const char curlx_base64encdec[] =
@@ -182,7 +182,7 @@
if(insize > CURL_MAX_BASE64_INPUT)
return CURLE_TOO_LARGE;
- base64data = output = curlx_malloc((insize + 2) / 3 * 4 + 1);
+ base64data = output = curlx_malloc(((insize + 2) / 3 * 4) + 1);
if(!output)
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/curlx/basename.c b/Utilities/cmcurl/lib/curlx/basename.c
new file mode 100644
index 0000000..d2fd160
--- /dev/null
+++ b/Utilities/cmcurl/lib/curlx/basename.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef HAVE_BASENAME
+
+#include "curlx/basename.h"
+
+/*
+ (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
+ Edition)
+
+ The basename() function shall take the pathname pointed to by path and
+ return a pointer to the final component of the pathname, deleting any
+ trailing '/' characters.
+
+ If the string pointed to by path consists entirely of the '/' character,
+ basename() shall return a pointer to the string "/". If the string pointed
+ to by path is exactly "//", it is implementation-defined whether '/' or "//"
+ is returned.
+
+ If path is a null pointer or points to an empty string, basename() shall
+ return a pointer to the string ".".
+
+ The basename() function may modify the string pointed to by path, and may
+ return a pointer to static storage that may then be overwritten by a
+ subsequent call to basename().
+
+ The basename() function need not be reentrant. A function that is not
+ required to be reentrant is not required to be thread-safe.
+
+*/
+char *curlx_basename(char *path)
+{
+ /* Ignore all the details above for now and make a quick and simple
+ implementation here */
+ char *s1;
+ char *s2;
+
+ s1 = strrchr(path, '/');
+ s2 = strrchr(path, '\\');
+
+ if(s1 && s2)
+ path = ((s1 > s2) ? s1 : s2) + 1;
+ else if(s1)
+ path = s1 + 1;
+ else if(s2)
+ path = s2 + 1;
+
+ return path;
+}
+
+#endif /* !HAVE_BASENAME */
diff --git a/Utilities/cmcurl/lib/curlx/basename.h b/Utilities/cmcurl/lib/curlx/basename.h
new file mode 100644
index 0000000..fb79fed
--- /dev/null
+++ b/Utilities/cmcurl/lib/curlx/basename.h
@@ -0,0 +1,39 @@
+#ifndef HEADER_CURLX_BASENAME_H
+#define HEADER_CURLX_BASENAME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef HAVE_BASENAME
+char *curlx_basename(char *path);
+#else
+
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#define curlx_basename(x) basename(x)
+#endif /* !HAVE_BASENAME */
+
+#endif /* HEADER_CURLX_BASENAME_H */
diff --git a/Utilities/cmcurl/lib/curlx/binmode.h b/Utilities/cmcurl/lib/curlx/binmode.h
deleted file mode 100644
index 991cc89..0000000
--- a/Utilities/cmcurl/lib/curlx/binmode.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef HEADER_CURL_TOOL_BINMODE_H
-#define HEADER_CURL_TOOL_BINMODE_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "../curl_setup.h"
-
-#if (defined(HAVE_SETMODE) || defined(HAVE__SETMODE)) && defined(O_BINARY)
-/* Requires io.h and/or fcntl.h when available */
-#ifdef HAVE__SETMODE
-# define CURLX_SET_BINMODE(stream) (void)_setmode(fileno(stream), O_BINARY)
-#else
-# define CURLX_SET_BINMODE(stream) (void)setmode(fileno(stream), O_BINARY)
-#endif
-#else
-# define CURLX_SET_BINMODE(stream) (void)stream
-#endif
-
-#endif /* HEADER_CURL_TOOL_BINMODE_H */
diff --git a/Utilities/cmcurl/lib/curlx/curlx.h b/Utilities/cmcurl/lib/curlx/curlx.h
index 817acb0..79cffc8 100644
--- a/Utilities/cmcurl/lib/curlx/curlx.h
+++ b/Utilities/cmcurl/lib/curlx/curlx.h
@@ -31,53 +31,22 @@
* be.
*/
-#include "binmode.h"
-/* "binmode.h" provides macro CURLX_SET_BINMODE() */
-
-#include "nonblock.h"
-/* "nonblock.h" provides curlx_nonblock() */
-
-#include "multibyte.h"
-/* "multibyte.h" provides these functions and macros:
-
- curlx_convert_UTF8_to_wchar()
- curlx_convert_wchar_to_UTF8()
- curlx_convert_UTF8_to_tchar()
- curlx_convert_tchar_to_UTF8()
-*/
-
-#include "version_win32.h"
-/* provides curlx_verify_windows_version() */
-
-#include "strerr.h"
-/* The curlx_strerror() function */
-
-#include "strparse.h"
-/* The curlx_str_* parsing functions */
-
-#include "strcopy.h"
-/* curlx_strcopy */
-
-#include "dynbuf.h"
-/* The curlx_dyn_* functions */
-
-#include "fopen.h"
-/* The curlx_f* functions */
-
-#include "base64.h"
-#include "timeval.h"
-#include "timediff.h"
-
-#include "wait.h"
-/* for curlx_wait_ms */
-
-#include "winapi.h"
-/* for curlx_winapi_strerror */
-
-#include "inet_pton.h"
-/* for curlx_inet_pton */
-
-#include "inet_ntop.h"
-/* for curlx_inet_ntop */
+#include "curlx/base64.h" /* for curlx_base64* */
+#include "curlx/basename.h" /* for curlx_basename() */
+#include "curlx/dynbuf.h" /* for curlx_dyn_*() */
+#include "curlx/fopen.h" /* for curlx_f*() */
+#include "curlx/inet_ntop.h" /* for curlx_inet_ntop() */
+#include "curlx/inet_pton.h" /* for curlx_inet_pton() */
+#include "curlx/multibyte.h" /* for curlx_convert_*() */
+#include "curlx/nonblock.h" /* for curlx_nonblock() */
+#include "curlx/strcopy.h" /* for curlx_strcopy() */
+#include "curlx/strdup.h" /* for curlx_memdup*() and curlx_tcsdup() */
+#include "curlx/strerr.h" /* for curlx_strerror() */
+#include "curlx/strparse.h" /* for curlx_str_* parsing functions */
+#include "curlx/timediff.h" /* for timediff_t type and related functions */
+#include "curlx/timeval.h" /* for curlx_now type and related functions */
+#include "curlx/version_win32.h" /* for curlx_verify_windows_version() */
+#include "curlx/wait.h" /* for curlx_wait_ms() */
+#include "curlx/winapi.h" /* for curlx_winapi_strerror() */
#endif /* HEADER_CURL_CURLX_H */
diff --git a/Utilities/cmcurl/lib/curlx/dynbuf.c b/Utilities/cmcurl/lib/curlx/dynbuf.c
index 158d4d0..7045a1f 100644
--- a/Utilities/cmcurl/lib/curlx/dynbuf.c
+++ b/Utilities/cmcurl/lib/curlx/dynbuf.c
@@ -21,10 +21,10 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "dynbuf.h"
-#include "../curl_printf.h"
+#include "curlx/dynbuf.h"
+#include "curl_printf.h"
#define MIN_FIRST_ALLOC 32
@@ -102,8 +102,6 @@
}
if(a != s->allc) {
- /* this logic is not using Curl_saferealloc() to make the tool not have to
- include that as well when it uses this code */
void *p = curlx_realloc(s->bufr, a);
if(!p) {
curlx_dyn_free(s);
diff --git a/Utilities/cmcurl/lib/curlx/fopen.c b/Utilities/cmcurl/lib/curlx/fopen.c
index e9eb6df..6d0ef7e 100644
--- a/Utilities/cmcurl/lib/curlx/fopen.c
+++ b/Utilities/cmcurl/lib/curlx/fopen.c
@@ -21,9 +21,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "fopen.h"
+#include "curlx/fopen.h"
int curlx_fseek(void *stream, curl_off_t offset, int whence)
{
@@ -42,10 +42,10 @@
#include <share.h> /* for _SH_DENYNO */
-#include "multibyte.h"
-#include "timeval.h"
+#include "curlx/multibyte.h"
+#include "curlx/timeval.h"
-#ifdef CURLDEBUG
+#ifdef CURL_MEMDEBUG
/*
* Use system allocators to avoid infinite recursion when called by curl's
* memory tracker memdebug functions.
@@ -405,7 +405,7 @@
return result;
}
-int curlx_win32_stat(const char *path, struct_stat *buffer)
+int curlx_win32_stat(const char *path, curlx_struct_stat *buffer)
{
int result = -1;
TCHAR *fixed = NULL;
@@ -439,8 +439,8 @@
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_COOKIES) || \
!defined(CURL_DISABLE_ALTSVC)
/* rename() on Windows does not overwrite, so we cannot use it here.
- MoveFileEx() will overwrite and is usually atomic, however it fails
- when there are open handles to the file. */
+ MoveFileEx() will overwrite and is usually atomic but fails when there are
+ open handles to the file. */
int curlx_win32_rename(const char *oldpath, const char *newpath)
{
int res = -1; /* fail */
diff --git a/Utilities/cmcurl/lib/curlx/fopen.h b/Utilities/cmcurl/lib/curlx/fopen.h
index 53c079e..d89830e 100644
--- a/Utilities/cmcurl/lib/curlx/fopen.h
+++ b/Utilities/cmcurl/lib/curlx/fopen.h
@@ -23,9 +23,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "multibyte.h"
+#include "curlx/multibyte.h"
#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for open() and attributes */
@@ -34,6 +34,7 @@
int curlx_fseek(void *stream, curl_off_t offset, int whence);
#ifdef _WIN32
+#include <sys/stat.h> /* for _fstati64(), struct _stati64 */
#ifndef CURL_WINDOWS_UWP
HANDLE curlx_CreateFile(const char *filename,
DWORD dwDesiredAccess,
@@ -43,25 +44,33 @@
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
#endif /* !CURL_WINDOWS_UWP */
+#define curlx_fstat _fstati64
+#define curlx_struct_stat struct _stati64
FILE *curlx_win32_fopen(const char *filename, const char *mode);
FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fh);
-int curlx_win32_stat(const char *path, struct_stat *buffer);
+int curlx_win32_stat(const char *path, curlx_struct_stat *buffer);
int curlx_win32_open(const char *filename, int oflag, ...);
int curlx_win32_rename(const char *oldpath, const char *newpath);
-#define CURLX_FOPEN_LOW(fname, mode) curlx_win32_fopen(fname, mode)
-#define CURLX_FREOPEN_LOW(fname, mode, fh) curlx_win32_freopen(fname, mode, fh)
-#define curlx_stat(fname, stp) curlx_win32_stat(fname, stp)
-#define curlx_open curlx_win32_open
-#define curlx_rename curlx_win32_rename
+#define CURLX_FOPEN_LOW curlx_win32_fopen
+#define CURLX_FREOPEN_LOW curlx_win32_freopen
+#define CURLX_FDOPEN_LOW _fdopen
+#define curlx_stat curlx_win32_stat
+#define curlx_open curlx_win32_open
+#define curlx_close _close
+#define curlx_rename curlx_win32_rename
#else
-#define CURLX_FOPEN_LOW fopen
-#define CURLX_FREOPEN_LOW freopen
-#define curlx_stat(fname, stp) stat(fname, stp)
-#define curlx_open open
-#define curlx_rename rename
+#define curlx_fstat fstat
+#define curlx_struct_stat struct stat
+#define CURLX_FOPEN_LOW fopen
+#define CURLX_FREOPEN_LOW freopen
+#define CURLX_FDOPEN_LOW fdopen
+#define curlx_stat stat
+#define curlx_open open
+#define curlx_close close
+#define curlx_rename rename
#endif
-#ifdef CURLDEBUG
+#ifdef CURL_MEMDEBUG
#define curlx_fopen(file, mode) curl_dbg_fopen(file, mode, __LINE__, __FILE__)
#define curlx_freopen(file, mode, fh) \
curl_dbg_freopen(file, mode, fh, __LINE__, __FILE__)
@@ -71,7 +80,7 @@
#else
#define curlx_fopen CURLX_FOPEN_LOW
#define curlx_freopen CURLX_FREOPEN_LOW
-#define curlx_fdopen fdopen
+#define curlx_fdopen CURLX_FDOPEN_LOW
#define curlx_fclose fclose
#endif
diff --git a/Utilities/cmcurl/lib/curlx/inet_ntop.c b/Utilities/cmcurl/lib/curlx/inet_ntop.c
index 6bea5e1..803b988 100644
--- a/Utilities/cmcurl/lib/curlx/inet_ntop.c
+++ b/Utilities/cmcurl/lib/curlx/inet_ntop.c
@@ -16,7 +16,7 @@
*
* SPDX-License-Identifier: ISC
*/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifndef HAVE_INET_NTOP
@@ -30,9 +30,9 @@
#include <arpa/inet.h>
#endif
-#include "inet_ntop.h"
-#include "snprintf.h"
-#include "strcopy.h"
+#include "curlx/inet_ntop.h"
+#include "curlx/snprintf.h"
+#include "curlx/strcopy.h"
#define IN6ADDRSZ 16
/* #define INADDRSZ 4 */
@@ -166,7 +166,7 @@
static const unsigned char ldigits[] = "0123456789abcdef";
unsigned int w = words[i];
- /* output lowercase 16bit hex number but ignore leading zeroes */
+ /* output lowercase 16-bit hex number but ignore leading zeroes */
if(w & 0xf000)
*tp++ = ldigits[(w & 0xf000) >> 12];
if(w & 0xff00)
diff --git a/Utilities/cmcurl/lib/curlx/inet_ntop.h b/Utilities/cmcurl/lib/curlx/inet_ntop.h
index 45b63d9..2e3419f 100644
--- a/Utilities/cmcurl/lib/curlx/inet_ntop.h
+++ b/Utilities/cmcurl/lib/curlx/inet_ntop.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef HAVE_INET_NTOP
#ifdef HAVE_NETINET_IN_H
@@ -37,7 +37,7 @@
#endif
#ifdef __AMIGA__
#define curlx_inet_ntop(af, addr, buf, size) \
- (char *)inet_ntop(af, CURL_UNCONST(addr), (unsigned char *)buf, \
+ (char *)inet_ntop(af, CURL_UNCONST(addr), (unsigned char *)(buf), \
(curl_socklen_t)(size))
#else
#define curlx_inet_ntop(af, addr, buf, size) \
diff --git a/Utilities/cmcurl/lib/curlx/inet_pton.c b/Utilities/cmcurl/lib/curlx/inet_pton.c
index 703a7b9..d3c53fb 100644
--- a/Utilities/cmcurl/lib/curlx/inet_pton.c
+++ b/Utilities/cmcurl/lib/curlx/inet_pton.c
@@ -17,9 +17,7 @@
*
* SPDX-License-Identifier: ISC
*/
-#include "../curl_setup.h"
-
-#include "strparse.h"
+#include "curl_setup.h"
#ifndef HAVE_INET_PTON
@@ -33,7 +31,8 @@
#include <arpa/inet.h>
#endif
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
+#include "curlx/strparse.h"
#define IN6ADDRSZ 16
#define INADDRSZ 4
@@ -53,41 +52,7 @@
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
-static int inet_pton4(const char *src, unsigned char *dst);
-static int inet_pton6(const char *src, unsigned char *dst);
-
-/* int
- * inet_pton(af, src, dst)
- * convert from presentation format (which usually means ASCII printable)
- * to network format (which is usually some kind of binary format).
- * return:
- * 1 if the address was valid for the specified address family
- * 0 if the address was not valid (`dst' is untouched in this case)
- * -1 if some other error occurred (`dst' is untouched in this case, too)
- * notice:
- * On Windows we store the error in the thread errno, not
- * in the Winsock error code. This is to avoid losing the
- * actual last Winsock error. When this function returns
- * -1, check errno not SOCKERRNO.
- * author:
- * Paul Vixie, 1996.
- */
-int curlx_inet_pton(int af, const char *src, void *dst)
-{
- switch(af) {
- case AF_INET:
- return inet_pton4(src, (unsigned char *)dst);
- case AF_INET6:
- return inet_pton6(src, (unsigned char *)dst);
- default:
- errno = SOCKEAFNOSUPPORT;
- return -1;
- }
- /* NOTREACHED */
-}
-
-/* int
- * inet_pton4(src, dst)
+/* int inet_pton4(src, dst)
* like inet_aton() but without all the hexadecimal and shorthand.
* return:
* 1 if `src' is a valid dotted quad, else 0.
@@ -105,7 +70,7 @@
octets = 0;
tp = tmp;
*tp = 0;
- while((ch = *src++) != '\0') {
+ while((ch = (unsigned char)*src++) != '\0') {
if(ISDIGIT(ch)) {
unsigned int val = (*tp * 10) + (ch - '0');
@@ -135,8 +100,7 @@
return 1;
}
-/* int
- * inet_pton6(src, dst)
+/* int inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
@@ -165,7 +129,7 @@
curtok = src;
saw_xdigit = 0;
val = 0;
- while((ch = *src++) != '\0') {
+ while((ch = (unsigned char)*src++) != '\0') {
if(ISXDIGIT(ch)) {
val <<= 4;
val |= curlx_hexval(ch);
@@ -225,4 +189,33 @@
return 1;
}
+/* int inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address was not valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * notice:
+ * On Windows we store the error in the thread errno, not
+ * in the Winsock error code. This is to avoid losing the
+ * actual last Winsock error. When this function returns
+ * -1, check errno not SOCKERRNO.
+ * author:
+ * Paul Vixie, 1996.
+ */
+int curlx_inet_pton(int af, const char *src, void *dst)
+{
+ switch(af) {
+ case AF_INET:
+ return inet_pton4(src, (unsigned char *)dst);
+ case AF_INET6:
+ return inet_pton6(src, (unsigned char *)dst);
+ default:
+ errno = SOCKEAFNOSUPPORT;
+ return -1;
+ }
+ /* NOTREACHED */
+}
+
#endif /* HAVE_INET_PTON */
diff --git a/Utilities/cmcurl/lib/curlx/inet_pton.h b/Utilities/cmcurl/lib/curlx/inet_pton.h
index fc3ae3d..02ae7f2 100644
--- a/Utilities/cmcurl/lib/curlx/inet_pton.h
+++ b/Utilities/cmcurl/lib/curlx/inet_pton.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef HAVE_INET_PTON
#ifdef HAVE_NETINET_IN_H
@@ -43,7 +43,7 @@
inet_pton(x, y, z)
#endif
#else
-int curlx_inet_pton(int, const char *, void *);
+int curlx_inet_pton(int af, const char *src, void *dst);
#endif /* HAVE_INET_PTON */
#endif /* HEADER_CURL_INET_PTON_H */
diff --git a/Utilities/cmcurl/lib/curlx/multibyte.c b/Utilities/cmcurl/lib/curlx/multibyte.c
index 529091a..715d2b8 100644
--- a/Utilities/cmcurl/lib/curlx/multibyte.c
+++ b/Utilities/cmcurl/lib/curlx/multibyte.c
@@ -21,11 +21,11 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#if defined(_WIN32) && defined(UNICODE)
-#include "multibyte.h"
+#include "curlx/multibyte.h"
/*
* MultiByte conversions using Windows kernel32 library.
diff --git a/Utilities/cmcurl/lib/curlx/multibyte.h b/Utilities/cmcurl/lib/curlx/multibyte.h
index 26da0f0..8863fb0 100644
--- a/Utilities/cmcurl/lib/curlx/multibyte.h
+++ b/Utilities/cmcurl/lib/curlx/multibyte.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef _WIN32
diff --git a/Utilities/cmcurl/lib/curlx/nonblock.c b/Utilities/cmcurl/lib/curlx/nonblock.c
index 96bf3db..6f6458f 100644
--- a/Utilities/cmcurl/lib/curlx/nonblock.c
+++ b/Utilities/cmcurl/lib/curlx/nonblock.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
@@ -35,7 +35,7 @@
#include <inet.h>
#endif
-#include "nonblock.h"
+#include "curlx/nonblock.h"
/*
* curlx_nonblock() set the given socket to either blocking or non-blocking
diff --git a/Utilities/cmcurl/lib/curlx/snprintf.c b/Utilities/cmcurl/lib/curlx/snprintf.c
new file mode 100644
index 0000000..c733252
--- /dev/null
+++ b/Utilities/cmcurl/lib/curlx/snprintf.c
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curlx/snprintf.h"
+
+#ifdef _WIN32
+#include <stdarg.h>
+
+/* Simplified wrapper for the Windows platform to use the correct symbol and
+ ensuring null-termination. Omit returning a length to keep it simple. */
+void curlx_win32_snprintf(char *buf, size_t maxlen, const char *fmt, ...)
+{
+ va_list ap;
+ if(!maxlen)
+ return;
+ va_start(ap, fmt);
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
+ /* !checksrc! disable BANNEDFUNC 1 */
+ (void)vsnprintf(buf, maxlen, fmt, ap);
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+ buf[maxlen - 1] = 0;
+ va_end(ap);
+}
+#endif /* _WIN32 */
diff --git a/Utilities/cmcurl/lib/curlx/snprintf.h b/Utilities/cmcurl/lib/curlx/snprintf.h
index 266ea13..d6260e4 100644
--- a/Utilities/cmcurl/lib/curlx/snprintf.h
+++ b/Utilities/cmcurl/lib/curlx/snprintf.h
@@ -1,3 +1,5 @@
+#ifndef HEADER_CURLX_SNPRINTF_H
+#define HEADER_CURLX_SNPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,12 +23,18 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#include "curl_setup.h"
/* Raw snprintf() for curlx */
+#ifdef _WIN32
+void curlx_win32_snprintf(char *buf, size_t maxlen, const char *fmt, ...)
+ CURL_PRINTF(3, 4);
+#endif
+
#ifdef WITHOUT_LIBCURL /* when built for the test servers */
-#if defined(_MSC_VER) && (_MSC_VER < 1900) /* adjust for old MSVC */
-#define SNPRINTF _snprintf
+#ifdef _WIN32
+#define SNPRINTF curlx_win32_snprintf
#else
#define SNPRINTF snprintf
#endif
@@ -34,3 +42,4 @@
#include <curl/mprintf.h>
#define SNPRINTF curl_msnprintf
#endif /* WITHOUT_LIBCURL */
+#endif /* HEADER_CURLX_SNPRINTF_H */
diff --git a/Utilities/cmcurl/lib/curlx/strcopy.c b/Utilities/cmcurl/lib/curlx/strcopy.c
index d6bff15..da137c3 100644
--- a/Utilities/cmcurl/lib/curlx/strcopy.c
+++ b/Utilities/cmcurl/lib/curlx/strcopy.c
@@ -21,9 +21,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "strcopy.h"
+#include "curlx/strcopy.h"
/*
* curlx_strcopy() is a replacement for strcpy.
diff --git a/Utilities/cmcurl/lib/curlx/strdup.c b/Utilities/cmcurl/lib/curlx/strdup.c
new file mode 100644
index 0000000..3c967db
--- /dev/null
+++ b/Utilities/cmcurl/lib/curlx/strdup.c
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef _WIN32
+#include <wchar.h>
+#endif
+
+#include "curlx/strdup.h"
+
+#ifdef _WIN32
+/***************************************************************************
+ *
+ * curlx_wcsdup(source)
+ *
+ * Copies the 'source' wchar string to a newly allocated buffer (that is
+ * returned). Used by macro curlx_tcsdup().
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+wchar_t *curlx_wcsdup(const wchar_t *src)
+{
+ size_t length = wcslen(src);
+
+ if(length > (SIZE_MAX / sizeof(wchar_t)) - 1)
+ return (wchar_t *)NULL; /* integer overflow */
+
+ return (wchar_t *)curlx_memdup(src, (length + 1) * sizeof(wchar_t));
+}
+#endif
+
+/***************************************************************************
+ *
+ * curlx_memdup(source, length)
+ *
+ * Copies the 'source' data to a newly allocated buffer (that is
+ * returned). Copies 'length' bytes.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *curlx_memdup(const void *src, size_t length)
+{
+ void *buffer = curlx_malloc(length);
+ if(!buffer)
+ return NULL; /* fail */
+
+ memcpy(buffer, src, length);
+
+ return buffer;
+}
+
+/***************************************************************************
+ *
+ * curlx_memdup0(source, length)
+ *
+ * Copies the 'source' string to a newly allocated buffer (that is returned).
+ * Copies 'length' bytes then adds a null-terminator.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *curlx_memdup0(const char *src, size_t length)
+{
+ char *buf = (length < SIZE_MAX) ? curlx_malloc(length + 1) : NULL;
+ if(!buf)
+ return NULL;
+ if(length) {
+ DEBUGASSERT(src); /* must never be NULL */
+ memcpy(buf, src, length);
+ }
+ buf[length] = 0;
+ return buf;
+}
diff --git a/Utilities/cmcurl/lib/curlx/strdup.h b/Utilities/cmcurl/lib/curlx/strdup.h
new file mode 100644
index 0000000..0c4b141
--- /dev/null
+++ b/Utilities/cmcurl/lib/curlx/strdup.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURLX_STRDUP_H
+#define HEADER_CURLX_STRDUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef _WIN32
+wchar_t *curlx_wcsdup(const wchar_t *src); /* for curlx_tcsdup() */
+#endif
+void *curlx_memdup(const void *src, size_t length);
+void *curlx_memdup0(const char *src, size_t length);
+#endif /* HEADER_CURLX_STRDUP_H */
diff --git a/Utilities/cmcurl/lib/curlx/strerr.c b/Utilities/cmcurl/lib/curlx/strerr.c
index 3f1b1f5..91a329e 100644
--- a/Utilities/cmcurl/lib/curlx/strerr.c
+++ b/Utilities/cmcurl/lib/curlx/strerr.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef HAVE_STRERROR_R
# if (!defined(HAVE_POSIX_STRERROR_R) && \
@@ -31,10 +31,10 @@
# endif
#endif
-#include "winapi.h"
-#include "snprintf.h"
-#include "strerr.h"
-#include "strcopy.h"
+#include "curlx/winapi.h"
+#include "curlx/snprintf.h"
+#include "curlx/strerr.h"
+#include "curlx/strcopy.h"
#ifdef USE_WINSOCK
/* This is a helper function for curlx_strerror that converts Winsock error
@@ -43,17 +43,14 @@
*/
static const char *get_winsock_error(int err, char *buf, size_t len)
{
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- const char *p;
- size_t alen;
-#endif
+ VERBOSE(const char *p);
if(!len)
return NULL;
*buf = '\0';
-#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#ifndef CURLVERBOSE
(void)err;
return NULL;
#else
@@ -223,8 +220,7 @@
default:
return NULL;
}
- alen = strlen(p);
- curlx_strcopy(buf, len, p, alen);
+ curlx_strcopy(buf, len, p, strlen(p));
return buf;
#endif
}
@@ -294,7 +290,7 @@
*/
{
char buffer[256];
- char *msg = strerror_r(err, buffer, sizeof(buffer));
+ const char *msg = strerror_r(err, buffer, sizeof(buffer));
if(msg && buflen > 1)
SNPRINTF(buf, buflen, "%s", msg);
else if(buflen > sizeof("Unknown error ") + 20)
diff --git a/Utilities/cmcurl/lib/curlx/strparse.c b/Utilities/cmcurl/lib/curlx/strparse.c
index f11b58b..138b3df 100644
--- a/Utilities/cmcurl/lib/curlx/strparse.c
+++ b/Utilities/cmcurl/lib/curlx/strparse.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "strparse.h"
+#include "curlx/strparse.h"
void curlx_str_init(struct Curl_str *out)
{
@@ -140,7 +140,7 @@
/* given an ASCII character and max ascii, return TRUE if valid */
#define valid_digit(x, m) \
- (((x) >= '0') && ((x) <= m) && curlx_hexasciitable[(x) - '0'])
+ (((x) >= '0') && ((x) <= (m)) && curlx_hexasciitable[(x) - '0'])
/* We use 16 for the zero index (and the necessary bitwise AND in the loop)
to be able to have a non-zero value there to make valid_digit() able to
@@ -172,7 +172,7 @@
/* special-case low max scenario because check needs to be different */
do {
int n = curlx_hexval(*p++);
- num = num * base + n;
+ num = (num * base) + n;
if(num > max)
return STRE_OVERFLOW;
} while(valid_digit(*p, m));
@@ -182,7 +182,7 @@
int n = curlx_hexval(*p++);
if(num > ((max - n) / base))
return STRE_OVERFLOW;
- num = num * base + n;
+ num = (num * base) + n;
} while(valid_digit(*p, m));
}
*nump = num;
diff --git a/Utilities/cmcurl/lib/curlx/strparse.h b/Utilities/cmcurl/lib/curlx/strparse.h
index ae8fd19..514203d 100644
--- a/Utilities/cmcurl/lib/curlx/strparse.h
+++ b/Utilities/cmcurl/lib/curlx/strparse.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#define STRE_OK 0
#define STRE_BIG 1
@@ -98,7 +98,8 @@
int curlx_str_nudge(struct Curl_str *str, size_t num);
-int curlx_str_cspn(const char **linep, struct Curl_str *out, const char *cspn);
+int curlx_str_cspn(const char **linep, struct Curl_str *out,
+ const char *reject);
void curlx_str_trimblanks(struct Curl_str *out);
void curlx_str_passblanks(const char **linep);
diff --git a/Utilities/cmcurl/lib/curlx/timediff.c b/Utilities/cmcurl/lib/curlx/timediff.c
index 694c8d8..2bf7869 100644
--- a/Utilities/cmcurl/lib/curlx/timediff.c
+++ b/Utilities/cmcurl/lib/curlx/timediff.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "timediff.h"
+#include "curlx/timediff.h"
/*
* Converts number of milliseconds into a timeval structure.
diff --git a/Utilities/cmcurl/lib/curlx/timediff.h b/Utilities/cmcurl/lib/curlx/timediff.h
index e19b0f4..1081c75 100644
--- a/Utilities/cmcurl/lib/curlx/timediff.h
+++ b/Utilities/cmcurl/lib/curlx/timediff.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
/* Use a larger type even for 32-bit time_t systems so that we can keep
microsecond accuracy in it */
diff --git a/Utilities/cmcurl/lib/curlx/timeval.c b/Utilities/cmcurl/lib/curlx/timeval.c
index fa7e528..435804c 100644
--- a/Utilities/cmcurl/lib/curlx/timeval.c
+++ b/Utilities/cmcurl/lib/curlx/timeval.c
@@ -21,58 +21,30 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "timeval.h"
+#include "curlx/timeval.h"
#ifdef _WIN32
-#include "version_win32.h"
-#include "../system_win32.h"
+#include "system_win32.h"
LARGE_INTEGER Curl_freq;
-bool Curl_isVistaOrGreater;
/* For tool or tests, we must initialize before calling curlx_now().
Providing this function here is wrong. */
void curlx_now_init(void)
{
- if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
- VERSION_GREATER_THAN_EQUAL))
- Curl_isVistaOrGreater = true;
- else
- Curl_isVistaOrGreater = false;
-
QueryPerformanceFrequency(&Curl_freq);
}
/* In case of bug fix this function has a counterpart in tool_util.c */
void curlx_pnow(struct curltime *pnow)
{
- bool isVistaOrGreater;
- isVistaOrGreater = Curl_isVistaOrGreater;
- if(isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
- LARGE_INTEGER count;
- LARGE_INTEGER freq;
- freq = Curl_freq;
- DEBUGASSERT(freq.QuadPart);
- QueryPerformanceCounter(&count);
- pnow->tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
- pnow->tv_usec = (int)((count.QuadPart % freq.QuadPart) * 1000000 /
- freq.QuadPart);
- }
- else {
- /* Disable /analyze warning that GetTickCount64 is preferred */
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:28159)
-#endif
- DWORD milliseconds = GetTickCount();
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
- pnow->tv_sec = (time_t)(milliseconds / 1000);
- pnow->tv_usec = (int)((milliseconds % 1000) * 1000);
- }
+ LARGE_INTEGER count;
+ DEBUGASSERT(Curl_freq.QuadPart);
+ QueryPerformanceCounter(&count);
+ pnow->tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart);
+ pnow->tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 /
+ Curl_freq.QuadPart);
}
#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \
@@ -81,19 +53,19 @@
void curlx_pnow(struct curltime *pnow)
{
/*
- ** clock_gettime() is granted to be increased monotonically when the
- ** monotonic clock is queried. Time starting point is unspecified, it
- ** could be the system start-up time, the Epoch, or something else,
- ** in any case the time starting point does not change once that the
- ** system has started up.
- */
+ * clock_gettime() is granted to be increased monotonically when the
+ * monotonic clock is queried. Time starting point is unspecified, it
+ * could be the system start-up time, the Epoch, or something else,
+ * in any case the time starting point does not change once that the
+ * system has started up.
+ */
struct timespec tsnow;
/*
- ** clock_gettime() may be defined by Apple's SDK as weak symbol thus
- ** code compiles but fails during runtime if clock_gettime() is
- ** called on unsupported OS version.
- */
+ * clock_gettime() may be defined by Apple's SDK as weak symbol thus
+ * code compiles but fails during runtime if clock_gettime() is
+ * called on unsupported OS version.
+ */
#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
(HAVE_BUILTIN_AVAILABLE == 1)
bool have_clock_gettime = FALSE;
@@ -124,10 +96,10 @@
pnow->tv_usec = (int)(tsnow.tv_nsec / 1000);
}
/*
- ** Even when the configure process has truly detected monotonic clock
- ** availability, it might happen that it is not actually available at
- ** runtime. When this occurs simply fallback to other time source.
- */
+ * Even when the configure process has truly detected monotonic clock
+ * availability, it might happen that it is not actually available at
+ * runtime. When this occurs, fallback to other time source.
+ */
#ifdef HAVE_GETTIMEOFDAY
else {
struct timeval now;
@@ -145,17 +117,16 @@
#elif defined(HAVE_MACH_ABSOLUTE_TIME)
-#include <stdint.h>
#include <mach/mach_time.h>
void curlx_pnow(struct curltime *pnow)
{
/*
- ** Monotonic timer on macOS is provided by mach_absolute_time(), which
- ** returns time in Mach "absolute time units," which are platform-dependent.
- ** To convert to nanoseconds, one must use conversion factors specified by
- ** mach_timebase_info().
- */
+ * Monotonic timer on macOS is provided by mach_absolute_time(), which
+ * returns time in Mach "absolute time units," which are platform-dependent.
+ * To convert to nanoseconds, one must use conversion factors specified by
+ * mach_timebase_info().
+ */
static mach_timebase_info_data_t timebase;
uint64_t usecs;
@@ -176,10 +147,10 @@
void curlx_pnow(struct curltime *pnow)
{
/*
- ** gettimeofday() is not granted to be increased monotonically, due to
- ** clock drifting and external source time synchronization it can jump
- ** forward or backward in time.
- */
+ * gettimeofday() is not granted to be increased monotonically, due to
+ * clock drifting and external source time synchronization it can jump
+ * forward or backward in time.
+ */
struct timeval now;
(void)gettimeofday(&now, NULL);
pnow->tv_sec = now.tv_sec;
@@ -191,8 +162,8 @@
void curlx_pnow(struct curltime *pnow)
{
/*
- ** time() returns the value of time in seconds since the Epoch.
- */
+ * time() returns the value of time in seconds since the Epoch.
+ */
pnow->tv_sec = time(NULL);
pnow->tv_usec = 0;
}
@@ -220,10 +191,9 @@
return TIMEDIFF_T_MAX;
else if(diff <= (TIMEDIFF_T_MIN / 1000))
return TIMEDIFF_T_MIN;
- return diff * 1000 + (newer->tv_usec - older->tv_usec) / 1000;
+ return (diff * 1000) + ((newer->tv_usec - older->tv_usec) / 1000);
}
-
timediff_t curlx_timediff_ms(struct curltime newer, struct curltime older)
{
return curlx_ptimediff_ms(&newer, &older);
@@ -241,7 +211,7 @@
return TIMEDIFF_T_MAX;
else if(diff <= (TIMEDIFF_T_MIN / 1000))
return TIMEDIFF_T_MIN;
- return diff * 1000 + (newer.tv_usec - older.tv_usec + 999) / 1000;
+ return (diff * 1000) + ((newer.tv_usec - older.tv_usec + 999) / 1000);
}
/*
@@ -256,7 +226,7 @@
return TIMEDIFF_T_MAX;
else if(diff <= (TIMEDIFF_T_MIN / 1000000))
return TIMEDIFF_T_MIN;
- return diff * 1000000 + newer->tv_usec - older->tv_usec;
+ return (diff * 1000000) + newer->tv_usec - older->tv_usec;
}
timediff_t curlx_timediff_us(struct curltime newer, struct curltime older)
diff --git a/Utilities/cmcurl/lib/curlx/timeval.h b/Utilities/cmcurl/lib/curlx/timeval.h
index 4aab175..c01f95d 100644
--- a/Utilities/cmcurl/lib/curlx/timeval.h
+++ b/Utilities/cmcurl/lib/curlx/timeval.h
@@ -23,9 +23,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "timediff.h"
+#include "curlx/timediff.h"
struct curltime {
time_t tv_sec; /* seconds */
diff --git a/Utilities/cmcurl/lib/curlx/version_win32.c b/Utilities/cmcurl/lib/curlx/version_win32.c
index a9a4ee3..296a38d 100644
--- a/Utilities/cmcurl/lib/curlx/version_win32.c
+++ b/Utilities/cmcurl/lib/curlx/version_win32.c
@@ -21,12 +21,13 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef _WIN32
-#include "version_win32.h"
+#include "curlx/version_win32.h"
+#ifndef CURL_WINDOWS_UWP
/* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW)
and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */
struct OUR_OSVERSIONINFOEXW {
@@ -43,6 +44,24 @@
UCHAR wReserved;
};
+typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN)
+ (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG);
+static RTLVERIFYVERSIONINFO_FN s_pRtlVerifyVersionInfo;
+
+void curlx_verify_windows_init(void)
+{
+#if defined(__clang__) && __clang_major__ >= 16
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-function-type-strict"
+#endif
+ s_pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN,
+ GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlVerifyVersionInfo"));
+#if defined(__clang__) && __clang_major__ >= 16
+#pragma clang diagnostic pop
+#endif
+}
+#endif /* !CURL_WINDOWS_UWP */
+
/*
* curlx_verify_windows_version()
*
@@ -115,24 +134,6 @@
DWORD dwTypeMask = VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
- typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN)
- (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG);
- static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo;
- static bool onetime = TRUE; /* safe because first call is during init */
-
- if(onetime) {
-#if defined(__clang__) && __clang_major__ >= 16
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-function-type-strict"
-#endif
- pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN,
- GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlVerifyVersionInfo"));
-#if defined(__clang__) && __clang_major__ >= 16
-#pragma clang diagnostic pop
-#endif
- onetime = FALSE;
- }
-
switch(condition) {
case VERSION_LESS_THAN:
majorCondition = VER_LESS;
@@ -203,8 +204,8 @@
the real version always, so we use the Rtl variant of the function when
possible. Note though the function signatures have underlying fundamental
types that are the same, the return values are different. */
- if(pRtlVerifyVersionInfo)
- matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
+ if(s_pRtlVerifyVersionInfo)
+ matched = !s_pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
else
matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, dwTypeMask, cm);
@@ -222,11 +223,11 @@
cm = VerSetConditionMask(0, VER_BUILDNUMBER, buildCondition);
dwTypeMask = VER_BUILDNUMBER;
- if(pRtlVerifyVersionInfo)
- matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
+ if(s_pRtlVerifyVersionInfo)
+ matched = !s_pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
else
matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver,
- dwTypeMask, cm);
+ dwTypeMask, cm);
}
#endif
diff --git a/Utilities/cmcurl/lib/curlx/version_win32.h b/Utilities/cmcurl/lib/curlx/version_win32.h
index a5fb8ff..c4a1c0f 100644
--- a/Utilities/cmcurl/lib/curlx/version_win32.h
+++ b/Utilities/cmcurl/lib/curlx/version_win32.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifdef _WIN32
@@ -43,6 +43,11 @@
PLATFORM_WINNT
} PlatformIdentifier;
+#ifdef CURL_WINDOWS_UWP
+#define curlx_verify_windows_init() Curl_nop_stmt
+#else
+void curlx_verify_windows_init(void);
+#endif
/* This is used to verify if we are running on a specific Windows version */
bool curlx_verify_windows_version(const unsigned int majorVersion,
const unsigned int minorVersion,
diff --git a/Utilities/cmcurl/lib/curlx/wait.c b/Utilities/cmcurl/lib/curlx/wait.c
index 2a9f54b..5278426 100644
--- a/Utilities/cmcurl/lib/curlx/wait.c
+++ b/Utilities/cmcurl/lib/curlx/wait.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
#ifndef HAVE_SELECT
#error "We cannot compile without select() support."
@@ -37,19 +37,19 @@
#include <dos.h> /* delay() */
#endif
-#include "timediff.h"
-#include "wait.h"
+#include "curlx/timediff.h"
+#include "curlx/wait.h"
/*
* Internal function used for waiting a specific amount of ms in
* Curl_socket_check() and Curl_poll() when no file descriptor is provided to
- * wait on, just being used to delay execution. Winsock select() and poll()
- * timeout mechanisms need a valid socket descriptor in a not null file
- * descriptor set to work. Waiting indefinitely with this function is not
- * allowed, a zero or negative timeout value will return immediately. Timeout
- * resolution, accuracy, as well as maximum supported value is system
- * dependent, neither factor is a critical issue for the intended use of this
- * function in the library.
+ * wait on, being used to delay execution. Winsock select() and poll() timeout
+ * mechanisms need a valid socket descriptor in a not null file descriptor set
+ * to work. Waiting indefinitely with this function is not allowed, a zero or
+ * negative timeout value will return immediately. Timeout resolution,
+ * accuracy, as well as maximum supported value is system dependent, neither
+ * factor is a critical issue for the intended use of this function in the
+ * library.
*
* Return values:
* -1 = system call error, or invalid timeout value
diff --git a/Utilities/cmcurl/lib/curlx/wait.h b/Utilities/cmcurl/lib/curlx/wait.h
index c140194..9b9c273 100644
--- a/Utilities/cmcurl/lib/curlx/wait.h
+++ b/Utilities/cmcurl/lib/curlx/wait.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
int curlx_wait_ms(timediff_t timeout_ms);
diff --git a/Utilities/cmcurl/lib/curlx/warnless.c b/Utilities/cmcurl/lib/curlx/warnless.c
index 8c1be2d..5fc36ac 100644
--- a/Utilities/cmcurl/lib/curlx/warnless.c
+++ b/Utilities/cmcurl/lib/curlx/warnless.c
@@ -21,9 +21,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#if defined(__INTEL_COMPILER) && defined(__unix__)
@@ -49,9 +49,8 @@
#define CURL_MASK_SSIZE_T (CURL_MASK_USIZE_T >> 1)
/*
-** unsigned long to unsigned char
-*/
-
+ * unsigned long to unsigned char
+ */
unsigned char curlx_ultouc(unsigned long ulnum)
{
#ifdef __INTEL_COMPILER
@@ -68,9 +67,8 @@
}
/*
-** unsigned size_t to signed int
-*/
-
+ * unsigned size_t to signed int
+ */
int curlx_uztosi(size_t uznum)
{
#ifdef __INTEL_COMPILER
@@ -87,9 +85,8 @@
}
/*
-** unsigned size_t to unsigned long
-*/
-
+ * unsigned size_t to unsigned long
+ */
unsigned long curlx_uztoul(size_t uznum)
{
#ifdef __INTEL_COMPILER
@@ -108,9 +105,8 @@
}
/*
-** unsigned size_t to unsigned int
-*/
-
+ * unsigned size_t to unsigned int
+ */
unsigned int curlx_uztoui(size_t uznum)
{
#ifdef __INTEL_COMPILER
@@ -129,9 +125,8 @@
}
/*
-** signed long to signed int
-*/
-
+ * signed long to signed int
+ */
int curlx_sltosi(long slnum)
{
#ifdef __INTEL_COMPILER
@@ -151,9 +146,8 @@
}
/*
-** signed long to unsigned int
-*/
-
+ * signed long to unsigned int
+ */
unsigned int curlx_sltoui(long slnum)
{
#ifdef __INTEL_COMPILER
@@ -173,9 +167,8 @@
}
/*
-** signed long to unsigned short
-*/
-
+ * signed long to unsigned short
+ */
unsigned short curlx_sltous(long slnum)
{
#ifdef __INTEL_COMPILER
@@ -193,9 +186,8 @@
}
/*
-** unsigned size_t to signed ssize_t
-*/
-
+ * unsigned size_t to signed ssize_t
+ */
ssize_t curlx_uztosz(size_t uznum)
{
#ifdef __INTEL_COMPILER
@@ -212,9 +204,8 @@
}
/*
-** signed curl_off_t to unsigned size_t
-*/
-
+ * signed curl_off_t to unsigned size_t
+ */
size_t curlx_sotouz(curl_off_t sonum)
{
#ifdef __INTEL_COMPILER
@@ -231,9 +222,8 @@
}
/*
-** signed ssize_t to signed int
-*/
-
+ * signed ssize_t to signed int
+ */
int curlx_sztosi(ssize_t sznum)
{
#ifdef __INTEL_COMPILER
@@ -253,9 +243,8 @@
}
/*
-** unsigned int to unsigned short
-*/
-
+ * unsigned int to unsigned short
+ */
unsigned short curlx_uitous(unsigned int uinum)
{
#ifdef __INTEL_COMPILER
@@ -272,9 +261,8 @@
}
/*
-** signed int to unsigned size_t
-*/
-
+ * signed int to unsigned size_t
+ */
size_t curlx_sitouz(int sinum)
{
#ifdef __INTEL_COMPILER
diff --git a/Utilities/cmcurl/lib/curlx/warnless.h b/Utilities/cmcurl/lib/curlx/warnless.h
index 8a62ccf..3d0341e 100644
--- a/Utilities/cmcurl/lib/curlx/warnless.h
+++ b/Utilities/cmcurl/lib/curlx/warnless.h
@@ -69,6 +69,6 @@
/* Convert a long to size_t, return FALSE if negative or too large
* and set 0 */
-bool curlx_sltouz(long sznum, size_t *puznum);
+bool curlx_sltouz(long slnum, size_t *puznum);
#endif /* HEADER_CURL_WARNLESS_H */
diff --git a/Utilities/cmcurl/lib/curlx/winapi.c b/Utilities/cmcurl/lib/curlx/winapi.c
index b46a5bf..3417df2 100644
--- a/Utilities/cmcurl/lib/curlx/winapi.c
+++ b/Utilities/cmcurl/lib/curlx/winapi.c
@@ -21,16 +21,16 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "../curl_setup.h"
+#include "curl_setup.h"
/*
* curlx_winapi_strerror:
* Variant of curlx_strerror if the error code is definitely Windows API.
*/
#ifdef _WIN32
-#include "winapi.h"
-#include "snprintf.h"
-#include "strcopy.h"
+#include "curlx/winapi.h"
+#include "curlx/snprintf.h"
+#include "curlx/strcopy.h"
/* This is a helper function for curlx_strerror that converts Windows API error
* codes (GetLastError) to error messages.
@@ -39,30 +39,27 @@
const char *curlx_get_winapi_error(DWORD err, char *buf, size_t buflen)
{
char *p;
- wchar_t wbuf[256];
- DWORD wlen;
if(!buflen)
return NULL;
- *buf = '\0';
- *wbuf = L'\0';
-
/* We return the local codepage version of the error string because if it is
output to the user's terminal it will likely be with functions which
expect the local codepage (eg fprintf, failf, infof). */
- wlen = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
- LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL);
- if(wlen && !wcstombs_s(NULL, buf, buflen, wbuf, wlen)) {
- /* Truncate multiple lines */
- p = strchr(buf, '\n');
- if(p) {
- if(p > buf && *(p - 1) == '\r')
- *(p - 1) = '\0';
- else
- *p = '\0';
- }
+ if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
+ LANG_NEUTRAL, buf, (DWORD)buflen, NULL)) {
+ *buf = '\0';
+ return NULL;
+ }
+
+ /* Truncate multiple lines */
+ p = strchr(buf, '\n');
+ if(p) {
+ if(p > buf && *(p - 1) == '\r')
+ *(p - 1) = '\0';
+ else
+ *p = '\0';
}
return *buf ? buf : NULL;
@@ -78,7 +75,7 @@
*buf = '\0';
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
if(!curlx_get_winapi_error(err, buf, buflen)) {
#if defined(__GNUC__) && __GNUC__ >= 7
#pragma GCC diagnostic push
diff --git a/Utilities/cmcurl/lib/cw-out.c b/Utilities/cmcurl/lib/cw-out.c
index 69fb344..554c32e 100644
--- a/Utilities/cmcurl/lib/cw-out.c
+++ b/Utilities/cmcurl/lib/cw-out.c
@@ -101,22 +101,6 @@
BIT(errored);
};
-static CURLcode cw_out_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes);
-static void cw_out_close(struct Curl_easy *data, struct Curl_cwriter *writer);
-static CURLcode cw_out_init(struct Curl_easy *data,
- struct Curl_cwriter *writer);
-
-const struct Curl_cwtype Curl_cwt_out = {
- "cw-out",
- NULL,
- cw_out_init,
- cw_out_write,
- cw_out_close,
- sizeof(struct cw_out_ctx)
-};
-
static CURLcode cw_out_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
@@ -198,6 +182,8 @@
size_t nwritten;
CURLcode result;
+ NOVERBOSE((void)otype);
+
DEBUGASSERT(data->conn);
*pnwritten = 0;
Curl_set_in_callback(data, TRUE);
@@ -206,11 +192,11 @@
CURL_TRC_WRITE(data, "[OUT] wrote %zu %s bytes -> %zu",
blen, (otype == CW_OUT_HDS) ? "header" : "body",
nwritten);
- if(CURL_WRITEFUNC_PAUSE == nwritten) {
- if(data->conn->handler->flags & PROTOPT_NONETWORK) {
+ if(nwritten == CURL_WRITEFUNC_PAUSE) {
+ if(data->conn->scheme->flags & PROTOPT_NONETWORK) {
/* Protocols that work without network cannot be paused. This is
- actually only FILE:// just now, and it cannot pause since the
- transfer is not done using the "normal" procedure. */
+ actually only FILE:// now, and it cannot pause since the transfer is
+ not done using the "normal" procedure. */
failf(data, "Write callback asked for PAUSE when not supported");
return CURLE_WRITE_ERROR;
}
@@ -219,7 +205,7 @@
result = Curl_xfer_pause_recv(data, TRUE);
return result ? result : CURLE_AGAIN;
}
- else if(CURL_WRITEFUNC_ERROR == nwritten) {
+ else if(nwritten == CURL_WRITEFUNC_ERROR) {
failf(data, "client returned ERROR on write of %zu bytes", blen);
return CURLE_WRITE_ERROR;
}
@@ -455,6 +441,15 @@
return CURLE_OK;
}
+const struct Curl_cwtype Curl_cwt_out = {
+ "cw-out",
+ NULL,
+ cw_out_init,
+ cw_out_write,
+ cw_out_close,
+ sizeof(struct cw_out_ctx)
+};
+
bool Curl_cw_out_is_paused(struct Curl_easy *data)
{
struct Curl_cwriter *cw_out;
@@ -465,7 +460,7 @@
return FALSE;
ctx = (struct cw_out_ctx *)cw_out;
- return ctx->paused;
+ return (bool)ctx->paused;
}
static CURLcode cw_out_flush(struct Curl_easy *data,
diff --git a/Utilities/cmcurl/lib/cw-pause.c b/Utilities/cmcurl/lib/cw-pause.c
index 481b9fb..ec61187 100644
--- a/Utilities/cmcurl/lib/cw-pause.c
+++ b/Utilities/cmcurl/lib/cw-pause.c
@@ -34,7 +34,7 @@
/* body dynbuf sizes */
#define CW_PAUSE_BUF_CHUNK (16 * 1024)
/* when content decoding, write data in chunks */
-#define CW_PAUSE_DEC_WRITE_CHUNK (4096)
+#define CW_PAUSE_DEC_WRITE_CHUNK 4096
struct cw_pause_buf {
struct cw_pause_buf *next;
@@ -70,23 +70,6 @@
size_t buf_total;
};
-static CURLcode cw_pause_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes);
-static void cw_pause_close(struct Curl_easy *data,
- struct Curl_cwriter *writer);
-static CURLcode cw_pause_init(struct Curl_easy *data,
- struct Curl_cwriter *writer);
-
-const struct Curl_cwtype Curl_cwt_pause = {
- "cw-pause",
- NULL,
- cw_pause_init,
- cw_pause_write,
- cw_pause_close,
- sizeof(struct cw_pause_ctx)
-};
-
static CURLcode cw_pause_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
@@ -220,6 +203,15 @@
return result;
}
+const struct Curl_cwtype Curl_cwt_pause = {
+ "cw-pause",
+ NULL,
+ cw_pause_init,
+ cw_pause_write,
+ cw_pause_close,
+ sizeof(struct cw_pause_ctx)
+};
+
CURLcode Curl_cw_pause_flush(struct Curl_easy *data)
{
struct Curl_cwriter *cw_pause;
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index 5839e80..fcdea91 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -22,6 +22,8 @@
*
***************************************************************************/
#include "curl_setup.h"
+#include "urldata.h"
+#include "dict.h"
#ifndef CURL_DISABLE_DICT
@@ -51,11 +53,9 @@
#include <unistd.h>
#endif
-#include "urldata.h"
#include "transfer.h"
#include "curl_trc.h"
#include "escape.h"
-#include "dict.h"
#define DICT_MATCH "/MATCH:"
#define DICT_MATCH2 "/M:"
@@ -65,41 +65,6 @@
#define DICT_DEFINE3 "/LOOKUP:"
-/*
- * Forward declarations.
- */
-
-static CURLcode dict_do(struct Curl_easy *data, bool *done);
-
-/*
- * DICT protocol handler.
- */
-
-const struct Curl_handler Curl_handler_dict = {
- "dict", /* scheme */
- ZERO_NULL, /* setup_connection */
- dict_do, /* do_it */
- ZERO_NULL, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- ZERO_NULL, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- PORT_DICT, /* defport */
- CURLPROTO_DICT, /* protocol */
- CURLPROTO_DICT, /* family */
- PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
-};
-
#define DYN_DICT_WORD 10000
static char *unescape_word(const char *input)
{
@@ -306,4 +271,44 @@
curlx_free(path);
return result;
}
+
+/*
+ * DICT protocol
+ */
+static const struct Curl_protocol Curl_protocol_dict = {
+ ZERO_NULL, /* setup_connection */
+ dict_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_pollset */
+ ZERO_NULL, /* doing_pollset */
+ ZERO_NULL, /* domore_pollset */
+ ZERO_NULL, /* perform_pollset */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* write_resp */
+ ZERO_NULL, /* write_resp_hd */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
+};
+
#endif /* CURL_DISABLE_DICT */
+
+/*
+ * DICT protocol handler.
+ */
+const struct Curl_scheme Curl_scheme_dict = {
+ "dict", /* scheme */
+#ifdef CURL_DISABLE_DICT
+ ZERO_NULL,
+#else
+ &Curl_protocol_dict,
+#endif
+ CURLPROTO_DICT, /* protocol */
+ CURLPROTO_DICT, /* family */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */
+ PORT_DICT, /* defport */
+};
diff --git a/Utilities/cmcurl/lib/dict.h b/Utilities/cmcurl/lib/dict.h
index 4025c8b..b5d6947 100644
--- a/Utilities/cmcurl/lib/dict.h
+++ b/Utilities/cmcurl/lib/dict.h
@@ -23,8 +23,6 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#ifndef CURL_DISABLE_DICT
-extern const struct Curl_handler Curl_handler_dict;
-#endif
+extern const struct Curl_scheme Curl_scheme_dict;
#endif /* HEADER_CURL_DICT_H */
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index 9052fab..4488d42 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -28,19 +28,19 @@
#include "urldata.h"
#include "curl_addrinfo.h"
#include "doh.h"
-
#include "curl_trc.h"
+#include "httpsrr.h"
#include "multiif.h"
#include "url.h"
#include "connect.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#include "curlx/dynbuf.h"
-#include "escape.h"
+#include "escape.h" /* for Curl_hexencode() */
#include "urlapi-int.h"
#define DNS_CLASS_IN 0x01
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
static const char * const errors[] = {
"",
"Bad label",
@@ -65,7 +65,7 @@
return "bad error code";
}
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* CURLVERBOSE */
/* @unittest 1655
*/
@@ -113,7 +113,7 @@
if(len < expected_len)
return DOH_TOO_SMALL_BUFFER;
- *dnsp++ = 0; /* 16 bit id */
+ *dnsp++ = 0; /* 16-bit id */
*dnsp++ = 0;
*dnsp++ = 0x01; /* |QR| Opcode |AA|TC|RD| Set the RD bit */
*dnsp++ = '\0'; /* |RA| Z | RCODE | */
@@ -129,7 +129,7 @@
/* encode each label and store it in the QNAME */
while(*hostp) {
size_t labellen;
- char *dot = strchr(hostp, '.');
+ const char *dot = strchr(hostp, '.');
if(dot)
labellen = dot - hostp;
else
@@ -152,10 +152,10 @@
*dnsp++ = 0; /* append zero-length label for root */
/* There are assigned TYPE codes beyond 255: use range [1..65535] */
- *dnsp++ = (unsigned char)(255 & (dnstype >> 8)); /* upper 8 bit TYPE */
- *dnsp++ = (unsigned char)(255 & dnstype); /* lower 8 bit TYPE */
+ *dnsp++ = (unsigned char)(255 & (dnstype >> 8)); /* upper 8-bit TYPE */
+ *dnsp++ = (unsigned char)(255 & dnstype); /* lower 8-bit TYPE */
- *dnsp++ = '\0'; /* upper 8 bit CLASS */
+ *dnsp++ = '\0'; /* upper 8-bit CLASS */
*dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */
*olen = dnsp - orig;
@@ -181,7 +181,7 @@
return realsize;
}
-#if defined(USE_HTTPSRR) && defined(DEBUGBUILD)
+#if defined(USE_HTTPSRR) && defined(DEBUGBUILD) && defined(CURLVERBOSE)
/* doh_print_buf truncates if the hex string will be more than this */
#define LOCAL_PB_HEXMAX 400
@@ -201,7 +201,6 @@
infof(data, "%s: len=%d, val=%s", prefix, (int)len, hexstr);
else
infof(data, "%s: len=%d (truncated)val=%s", prefix, (int)len, hexstr);
- return;
}
#endif
@@ -304,8 +303,8 @@
goto error;
}
- timeout_ms = Curl_timeleft_ms(data, TRUE);
- if(timeout_ms <= 0) {
+ timeout_ms = Curl_timeleft_ms(data);
+ if(timeout_ms < 0) {
result = CURLE_OPERATION_TIMEDOUT;
goto error;
}
@@ -324,9 +323,7 @@
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- doh->state.feat = &Curl_trc_feat_dns;
-#endif
+ VERBOSE(doh->state.feat = &Curl_trc_feat_dns);
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_probe_write_cb);
@@ -495,7 +492,7 @@
#endif
#ifdef USE_HTTPSRR
- if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ if(conn->scheme->protocol & PROTO_FAMILY_HTTP) {
/* Only use HTTPS RR for HTTP(S) transfers */
char *qname = NULL;
if(port != PORT_HTTPS) {
@@ -594,7 +591,7 @@
/* silently ignore RRs over the limit */
if(d->numhttps_rrs < DOH_MAX_HTTPS) {
struct dohhttps_rr *h = &d->https_rrs[d->numhttps_rrs];
- h->val = Curl_memdup(&doh[index], len);
+ h->val = curlx_memdup(&doh[index], len);
if(!h->val)
return DOH_OUT_OF_MEM;
h->len = len;
@@ -692,10 +689,10 @@
return rc;
break;
case CURL_DNS_TYPE_DNAME:
- /* explicit for clarity; just skip; rely on synthesized CNAME */
+ /* explicit for clarity; skip; rely on synthesized CNAME */
break;
default:
- /* unsupported type, just skip it */
+ /* unsupported type, skip it */
break;
}
return DOH_OK;
@@ -757,9 +754,9 @@
return DOH_DNS_OUT_OF_RANGE;
type = doh_get16bit(doh, index);
- if((type != CURL_DNS_TYPE_CNAME) /* may be synthesized from DNAME */
- && (type != CURL_DNS_TYPE_DNAME) /* if present, accept and ignore */
- && (type != dnstype))
+ if((type != CURL_DNS_TYPE_CNAME) && /* may be synthesized from DNAME */
+ (type != CURL_DNS_TYPE_DNAME) && /* if present, accept and ignore */
+ (type != dnstype))
/* Not the same type as was asked for nor CNAME nor DNAME */
return DOH_DNS_UNEXPECTED_TYPE;
index += 2;
@@ -853,7 +850,7 @@
return DOH_OK; /* ok */
}
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
static void doh_show(struct Curl_easy *data,
const struct dohentry *d)
{
@@ -886,13 +883,13 @@
}
#ifdef USE_HTTPSRR
for(i = 0; i < d->numhttps_rrs; i++) {
-# ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
doh_print_buf(data, "DoH HTTPS", d->https_rrs[i].val, d->https_rrs[i].len);
-# else
+#else
infof(data, "DoH HTTPS RR: length %d", d->https_rrs[i].len);
-# endif
- }
#endif
+ }
+#endif /* USE_HTTPSRR */
for(i = 0; i < d->numcname; i++) {
infof(data, "CNAME: %s", curlx_dyn_ptr(&d->cname[i]));
}
@@ -982,7 +979,7 @@
addr = (void *)ai->ai_addr; /* storage area for this info */
DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4));
memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr));
- addr->sin_family = (CURL_SA_FAMILY_T)addrtype;
+ addr->sin_family = addrtype;
addr->sin_port = htons((unsigned short)port);
break;
@@ -991,7 +988,7 @@
addr6 = (void *)ai->ai_addr; /* storage area for this info */
DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr));
- addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype;
+ addr6->sin6_family = addrtype;
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
@@ -1009,7 +1006,7 @@
return result;
}
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef CURLVERBOSE
static const char *doh_type2name(DNStype dnstype)
{
switch(dnstype) {
@@ -1051,9 +1048,9 @@
* The encoding here is defined in
* https://datatracker.ietf.org/doc/html/rfc1035#section-3.1
*
- * The input buffer pointer will be modified so it points to
- * just after the end of the DNS name encoding on output. (And
- * that is why it is an "unsigned char **" :-)
+ * The input buffer pointer will be modified so it points to after the end of
+ * the DNS name encoding on output. (And that is why it is an "unsigned char
+ * **" :-)
*/
static CURLcode doh_decode_rdata_name(const unsigned char **buf,
size_t *remaining, char **dnsname)
@@ -1157,7 +1154,7 @@
return result;
}
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
UNITTEST void doh_print_httpsrr(struct Curl_easy *data,
struct Curl_https_rrinfo *hrr);
@@ -1193,7 +1190,6 @@
}
else
infof(data, "HTTPS RR: no ipv6hints");
- return;
}
# endif
#endif
@@ -1233,12 +1229,10 @@
rc[slot] = doh_resp_decode(curlx_dyn_uptr(&p->body),
curlx_dyn_len(&p->body),
p->dnstype, &de);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(rc[slot]) {
CURL_TRC_DNS(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
doh_type2name(p->dnstype), dohp->host);
}
-#endif
} /* next slot */
result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
@@ -1257,7 +1251,8 @@
goto error;
/* we got a response, create a dns entry. */
- dns = Curl_dnscache_mk_entry(data, ai, dohp->host, 0, dohp->port, FALSE);
+ dns = Curl_dnscache_mk_entry(data, &ai, dohp->host, 0,
+ dohp->port, FALSE);
if(dns) {
/* Now add and HTTPSRR information if we have */
#ifdef USE_HTTPSRR
@@ -1271,19 +1266,17 @@
goto error;
}
infof(data, "Some HTTPS RR to process");
-# ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
doh_print_httpsrr(data, hrr);
-# endif
+#endif
dns->hinfo = hrr;
}
-#endif
+#endif /* USE_HTTPSRR */
/* and add the entry to the cache */
data->state.async.dns = dns;
result = Curl_dnscache_add(data, dns);
*dnsp = data->state.async.dns;
}
- else
- Curl_freeaddrinfo(ai);
} /* address processing done */
/* All done */
diff --git a/Utilities/cmcurl/lib/doh.h b/Utilities/cmcurl/lib/doh.h
index 43bc323..3eba4df 100644
--- a/Utilities/cmcurl/lib/doh.h
+++ b/Utilities/cmcurl/lib/doh.h
@@ -23,26 +23,20 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-
#include "urldata.h"
-#include "curl_addrinfo.h"
-#ifdef USE_HTTPSRR
-# include <stdint.h>
-# include "httpsrr.h"
-#endif
#ifndef CURL_DISABLE_DOH
typedef enum {
DOH_OK,
- DOH_DNS_BAD_LABEL, /* 1 */
- DOH_DNS_OUT_OF_RANGE, /* 2 */
- DOH_DNS_LABEL_LOOP, /* 3 */
- DOH_TOO_SMALL_BUFFER, /* 4 */
- DOH_OUT_OF_MEM, /* 5 */
- DOH_DNS_RDATA_LEN, /* 6 */
- DOH_DNS_MALFORMAT, /* 7 */
- DOH_DNS_BAD_RCODE, /* 8 - no such name */
+ DOH_DNS_BAD_LABEL, /* 1 */
+ DOH_DNS_OUT_OF_RANGE, /* 2 */
+ DOH_DNS_LABEL_LOOP, /* 3 */
+ DOH_TOO_SMALL_BUFFER, /* 4 */
+ DOH_OUT_OF_MEM, /* 5 */
+ DOH_DNS_RDATA_LEN, /* 6 */
+ DOH_DNS_MALFORMAT, /* 7 */
+ DOH_DNS_BAD_RCODE, /* 8 - no such name */
DOH_DNS_UNEXPECTED_TYPE, /* 9 */
DOH_DNS_UNEXPECTED_CLASS, /* 10 */
DOH_NO_CONTENT, /* 11 */
@@ -120,7 +114,7 @@
int port, int ip_version);
CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
- struct Curl_dns_entry **dns);
+ struct Curl_dns_entry **dnsp);
#define DOH_MAX_ADDR 24
#define DOH_MAX_CNAME 4
diff --git a/Utilities/cmcurl/lib/dynhds.c b/Utilities/cmcurl/lib/dynhds.c
index c69d312..7424a57 100644
--- a/Utilities/cmcurl/lib/dynhds.c
+++ b/Utilities/cmcurl/lib/dynhds.c
@@ -26,11 +26,6 @@
#include "dynhds.h"
#include "strcase.h"
-#ifdef USE_NGHTTP2
-#include <stdint.h>
-#include <nghttp2/nghttp2.h>
-#endif /* USE_NGHTTP2 */
-
static struct dynhds_entry *entry_new(const char *name, size_t namelen,
const char *value, size_t valuelen,
int opts)
diff --git a/Utilities/cmcurl/lib/dynhds.h b/Utilities/cmcurl/lib/dynhds.h
index 170721c..e30eb45 100644
--- a/Utilities/cmcurl/lib/dynhds.h
+++ b/Utilities/cmcurl/lib/dynhds.h
@@ -50,7 +50,7 @@
int opts;
};
-#define DYNHDS_OPT_NONE (0)
+#define DYNHDS_OPT_NONE 0
#define DYNHDS_OPT_LOWERCASE (1 << 0)
/**
@@ -153,16 +153,14 @@
const char *name, const char *value);
/**
- * Add a single header from an HTTP/1.1 formatted line at the end. Line
- * may contain a delimiting CRLF or just LF. Any characters after
- * that will be ignored.
+ * Add a single header from an HTTP/1.1 formatted line at the end. Line may
+ * contain a delimiting CRLF or LF. Any characters after that will be ignored.
*/
CURLcode Curl_dynhds_h1_cadd_line(struct dynhds *dynhds, const char *line);
/**
- * Add a single header from an HTTP/1.1 formatted line at the end. Line
- * may contain a delimiting CRLF or just LF. Any characters after
- * that will be ignored.
+ * Add a single header from an HTTP/1.1 formatted line at the end. Line may
+ * contain a delimiting CRLF or LF. Any characters after that will be ignored.
*/
CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
const char *line, size_t line_len);
@@ -175,7 +173,6 @@
#ifdef USE_NGHTTP2
-#include <stdint.h>
#include <nghttp2/nghttp2.h>
nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount);
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index 398b20e..d05674e 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -51,7 +51,7 @@
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#include "easyif.h"
#include "multiif.h"
#include "multi_ev.h"
@@ -94,21 +94,6 @@
#endif
-/*
- * strdup (and other memory functions) is redefined in complicated
- * ways, but at this point it must be defined as the system-supplied strdup
- * so the callback pointer is initialized correctly.
- */
-#ifdef HAVE_STRDUP
-#ifdef _WIN32
-#define system_strdup _strdup
-#else
-#define system_strdup strdup
-#endif
-#else
-#define system_strdup Curl_strdup
-#endif
-
#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(push)
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
@@ -121,7 +106,7 @@
curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
-curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
+curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)CURLX_STRDUP_LOW;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(_MSC_VER) && defined(_DLL)
@@ -146,7 +131,7 @@
Curl_cmalloc = (curl_malloc_callback)malloc;
Curl_cfree = (curl_free_callback)free;
Curl_crealloc = (curl_realloc_callback)realloc;
- Curl_cstrdup = (curl_strdup_callback)system_strdup;
+ Curl_cstrdup = (curl_strdup_callback)CURLX_STRDUP_LOW;
Curl_ccalloc = (curl_calloc_callback)calloc;
}
@@ -361,7 +346,7 @@
}
global_init_unlock();
- /* We use curl_open() with undefined URL so far */
+ /* We use Curl_open() with undefined URL so far */
result = Curl_open(&data);
if(result) {
DEBUGF(curl_mfprintf(stderr, "Error: Curl_open failed\n"));
@@ -618,7 +603,9 @@
if(!pollrc) {
/* timeout! */
ev->ms = 0;
- /* curl_mfprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */
+#if 0
+ curl_mfprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n");
+#endif
mresult = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
&ev->running_handles);
}
@@ -737,7 +724,7 @@
* easy handle, destroys the multi handle and returns the easy handle's return
* code.
*
- * REALITY: it cannot just create and destroy the multi handle that easily. It
+ * REALITY: it cannot create and destroy the multi handle that easily. It
* needs to keep it around since if this easy handle is used again by this
* function, the same multi handle must be reused so that the same pools and
* caches can be used.
@@ -750,7 +737,7 @@
struct Curl_multi *multi;
CURLMcode mresult;
CURLcode result = CURLE_OK;
- SIGPIPE_VARIABLE(pipe_st);
+ struct Curl_sigpipe_ctx sigpipe_ctx;
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -807,8 +794,8 @@
/* assign this after curl_multi_add_handle() */
data->multi_easy = multi;
- sigpipe_init(&pipe_st);
- sigpipe_apply(data, &pipe_st);
+ sigpipe_init(&sigpipe_ctx);
+ sigpipe_apply(data, &sigpipe_ctx);
/* run the transfer */
result = events ? easy_events(multi) : easy_transfer(multi);
@@ -817,7 +804,7 @@
a failure here, room for future improvement! */
(void)curl_multi_remove_handle(multi, data);
- sigpipe_restore(&pipe_st);
+ sigpipe_restore(&sigpipe_ctx);
/* The multi handle is kept alive, owned by the easy handle */
return result;
@@ -851,10 +838,10 @@
{
struct Curl_easy *data = ptr;
if(GOOD_EASY_HANDLE(data)) {
- SIGPIPE_VARIABLE(pipe_st);
- sigpipe_ignore(data, &pipe_st);
+ struct Curl_sigpipe_ctx sigpipe_ctx;
+ sigpipe_ignore(data, &sigpipe_ctx);
Curl_close(&data);
- sigpipe_restore(&pipe_st);
+ sigpipe_restore(&sigpipe_ctx);
}
}
@@ -891,8 +878,9 @@
/* Copy src->set into dst->set first, then deal with the strings
afterwards */
dst->set = src->set;
- Curl_mime_initpart(&dst->set.mimepost);
-
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
+ dst->set.mimepostp = NULL;
+#endif
/* clear all dest string and blob pointers first, in case we error out
mid-function */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
@@ -918,17 +906,28 @@
if(src->set.postfieldsize == -1)
dst->set.str[i] = curlx_strdup(src->set.str[i]);
else
- /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
- dst->set.str[i] = Curl_memdup(src->set.str[i],
- curlx_sotouz(src->set.postfieldsize));
+ /* postfieldsize is curl_off_t, curlx_memdup() takes a size_t ... */
+ dst->set.str[i] = curlx_memdup(src->set.str[i],
+ curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str[i])
return CURLE_OUT_OF_MEMORY;
/* point to the new copy */
dst->set.postfields = dst->set.str[i];
}
- /* Duplicate mime data. */
- result = Curl_mime_duppart(dst, &dst->set.mimepost, &src->set.mimepost);
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
+ if(src->set.mimepostp) {
+ /* Duplicate mime data. Get a mimepost struct for the clone as well */
+ dst->set.mimepostp = curlx_malloc(sizeof(*dst->set.mimepostp));
+ if(!dst->set.mimepostp)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_mime_initpart(dst->set.mimepostp);
+ result = Curl_mime_duppart(dst, dst->set.mimepostp, src->set.mimepostp);
+ if(result)
+ return result;
+ }
+#endif
if(src->set.resolve)
dst->state.resolve = dst->set.resolve;
@@ -1275,7 +1274,7 @@
{
CURLcode result;
struct connectdata *c = NULL;
- SIGPIPE_VARIABLE(pipe_st);
+ struct Curl_sigpipe_ctx sigpipe_ctx;
*n = 0;
result = easy_connection(data, &c);
@@ -1287,9 +1286,9 @@
needs to be reattached */
Curl_attach_connection(data, c);
- sigpipe_ignore(data, &pipe_st);
+ sigpipe_ignore(data, &sigpipe_ctx);
result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, FALSE, n);
- sigpipe_restore(&pipe_st);
+ sigpipe_restore(&sigpipe_ctx);
if(result && result != CURLE_AGAIN)
return CURLE_SEND_ERROR;
diff --git a/Utilities/cmcurl/lib/easy_lock.h b/Utilities/cmcurl/lib/easy_lock.h
index 10c84c6..cefb01d 100644
--- a/Utilities/cmcurl/lib/easy_lock.h
+++ b/Utilities/cmcurl/lib/easy_lock.h
@@ -27,7 +27,7 @@
#define GLOBAL_INIT_IS_THREADSAFE
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+#ifdef _WIN32
#define curl_simple_lock SRWLOCK
#define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT
@@ -72,8 +72,6 @@
__builtin_ia32_pause();
#elif defined(__aarch64__)
__asm__ volatile("yield" ::: "memory");
-#elif defined(_WIN32)
- Sleep(1);
#elif defined(HAVE_SCHED_YIELD)
sched_yield();
#endif
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index afdf18c..be44e97 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/lib/escape.c
@@ -63,7 +63,7 @@
if(length > SIZE_MAX / 16)
return NULL;
- curlx_dyn_init(&d, length * 3 + 1);
+ curlx_dyn_init(&d, (length * 3) + 1);
while(length--) {
/* treat the characters unsigned */
diff --git a/Utilities/cmcurl/lib/escape.h b/Utilities/cmcurl/lib/escape.h
index 2ea06c4..9f9a89e 100644
--- a/Utilities/cmcurl/lib/escape.h
+++ b/Utilities/cmcurl/lib/escape.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
/* Escape and unescape URL encoding in strings. The functions return a new
- * allocated string or NULL if an error occurred. */
+ * allocated string or NULL if an error occurred. */
enum urlreject {
REJECT_NADA = 2,
diff --git a/Utilities/cmcurl/lib/fake_addrinfo.c b/Utilities/cmcurl/lib/fake_addrinfo.c
index bf5a448..d8b1398 100644
--- a/Utilities/cmcurl/lib/fake_addrinfo.c
+++ b/Utilities/cmcurl/lib/fake_addrinfo.c
@@ -67,8 +67,8 @@
for(ai = aihead->nodes; ai != NULL; ai = ai->ai_next) {
size_t ss_size;
size_t namelen = name ? strlen(name) + 1 : 0;
- /* ignore elements with unsupported address family, */
- /* settle family-specific sockaddr structure size. */
+ /* ignore elements with unsupported address family,
+ settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
else if(ai->ai_family == AF_INET6)
@@ -90,8 +90,8 @@
return NULL;
}
- /* copy each structure member individually, member ordering, */
- /* size, or padding might be different for each platform. */
+ /* copy each structure member individually, member ordering,
+ size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
diff --git a/Utilities/cmcurl/lib/fake_addrinfo.h b/Utilities/cmcurl/lib/fake_addrinfo.h
index db701be..07d5b6d 100644
--- a/Utilities/cmcurl/lib/fake_addrinfo.h
+++ b/Utilities/cmcurl/lib/fake_addrinfo.h
@@ -29,8 +29,8 @@
#include <ares.h>
#endif
-#if defined(CURLDEBUG) && defined(USE_ARES) && defined(HAVE_GETADDRINFO) && \
- (ARES_VERSION >= 0x011a00) /* >= 1.26.0 */
+#if defined(CURL_MEMDEBUG) && defined(HAVE_GETADDRINFO) && \
+ defined(USE_ARES) && (ARES_VERSION >= 0x011a00) /* >= 1.26.0 */
#define USE_FAKE_GETADDRINFO 1
#endif
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 982f254..1c3f663 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -22,6 +22,8 @@
*
***************************************************************************/
#include "curl_setup.h"
+#include "urldata.h"
+#include "file.h"
#ifndef CURL_DISABLE_FILE
@@ -53,12 +55,10 @@
#include <dirent.h>
#endif
-#include "urldata.h"
#include "progress.h"
#include "sendf.h"
#include "curl_trc.h"
#include "escape.h"
-#include "file.h"
#include "multiif.h"
#include "transfer.h"
#include "url.h"
@@ -82,55 +82,12 @@
int fd; /* open file descriptor to read from! */
};
-/*
- * Forward declarations.
- */
-
-static CURLcode file_do(struct Curl_easy *data, bool *done);
-static CURLcode file_done(struct Curl_easy *data,
- CURLcode status, bool premature);
-static CURLcode file_connect(struct Curl_easy *data, bool *done);
-static CURLcode file_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection);
-static CURLcode file_setup_connection(struct Curl_easy *data,
- struct connectdata *conn);
-
-/*
- * FILE scheme handler.
- */
-
-const struct Curl_handler Curl_handler_file = {
- "file", /* scheme */
- file_setup_connection, /* setup_connection */
- file_do, /* do_it */
- file_done, /* done */
- ZERO_NULL, /* do_more */
- file_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_pollset */
- ZERO_NULL, /* doing_pollset */
- ZERO_NULL, /* domore_pollset */
- ZERO_NULL, /* perform_pollset */
- file_disconnect, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- ZERO_NULL, /* follow */
- 0, /* defport */
- CURLPROTO_FILE, /* protocol */
- CURLPROTO_FILE, /* family */
- PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
-};
-
static void file_cleanup(struct FILEPROTO *file)
{
Curl_safefree(file->freepath);
file->path = NULL;
if(file->fd != -1) {
- close(file->fd);
+ curlx_close(file->fd);
file->fd = -1;
}
}
@@ -158,6 +115,19 @@
return CURLE_OK;
}
+static CURLcode file_done(struct Curl_easy *data,
+ CURLcode status, bool premature)
+{
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
+ (void)status;
+ (void)premature;
+
+ if(file)
+ file_cleanup(file);
+
+ return CURLE_OK;
+}
+
/*
* file_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. We emulate a
@@ -234,7 +204,7 @@
return CURLE_URL_MALFORMAT;
}
- #ifdef AMIGA_FILESYSTEM
+#ifdef AMIGA_FILESYSTEM
/*
* A leading slash in an AmigaDOS path denotes the parent
* directory, and hence we block this as it is relative.
@@ -257,10 +227,10 @@
fd = curlx_open(real_path, O_RDONLY);
}
}
- #else
+#else
fd = curlx_open(real_path, O_RDONLY);
file->path = real_path;
- #endif
+#endif
#endif
curlx_free(file->freepath);
file->freepath = real_path; /* free this when done */
@@ -276,19 +246,6 @@
return CURLE_OK;
}
-static CURLcode file_done(struct Curl_easy *data,
- CURLcode status, bool premature)
-{
- struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
- (void)status;
- (void)premature;
-
- if(file)
- file_cleanup(file);
-
- return CURLE_OK;
-}
-
static CURLcode file_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
@@ -313,7 +270,7 @@
CURLcode result = CURLE_OK;
char *xfer_ulbuf;
size_t xfer_ulblen;
- struct_stat file_stat;
+ curlx_struct_stat file_stat;
const char *sendbuf;
bool eos = FALSE;
@@ -354,8 +311,8 @@
/* treat the negative resume offset value as the case of "-" */
if(data->state.resume_from < 0) {
- if(fstat(fd, &file_stat)) {
- close(fd);
+ if(curlx_fstat(fd, &file_stat)) {
+ curlx_close(fd);
failf(data, "cannot get the size of %s", file->path);
return CURLE_WRITE_ERROR;
}
@@ -410,7 +367,7 @@
result = Curl_pgrsUpdate(data);
out:
- close(fd);
+ curlx_close(fd);
Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
return result;
@@ -433,9 +390,7 @@
*/
struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
CURLcode result = CURLE_OK;
- struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
- Windows version to have a different struct without
- having to redefine the simple word 'stat' */
+ curlx_struct_stat statbuf;
curl_off_t expected_size = -1;
bool size_known;
bool fstated = FALSE;
@@ -454,7 +409,7 @@
fd = file->fd;
/* VMS: This only works reliable for STREAMLF files */
- if(fstat(fd, &statbuf) != -1) {
+ if(curlx_fstat(fd, &statbuf) != -1) {
if(!S_ISDIR(statbuf.st_mode))
expected_size = statbuf.st_size;
/* and store the modification time */
@@ -560,13 +515,8 @@
if(data->state.resume_from) {
if(!S_ISDIR(statbuf.st_mode)) {
-#ifdef __AMIGA__
if(data->state.resume_from !=
- lseek(fd, (off_t)data->state.resume_from, SEEK_SET))
-#else
- if(data->state.resume_from !=
- lseek(fd, data->state.resume_from, SEEK_SET))
-#endif
+ curl_lseek(fd, data->state.resume_from, SEEK_SET))
return CURLE_BAD_DOWNLOAD_RESUME;
}
else {
@@ -648,4 +598,40 @@
return result;
}
+static const struct Curl_protocol Curl_protocol_file = {
+ file_setup_connection, /* setup_connection */
+ file_do, /* do_it */
+ file_done, /* done */
+ ZERO_NULL, /* do_more */
+ file_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_pollset */
+ ZERO_NULL, /* doing_pollset */
+ ZERO_NULL, /* domore_pollset */
+ ZERO_NULL, /* perform_pollset */
+ file_disconnect, /* disconnect */
+ ZERO_NULL, /* write_resp */
+ ZERO_NULL, /* write_resp_hd */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
+};
+
#endif
+
+/*
+ * FILE scheme handler.
+ */
+const struct Curl_scheme Curl_scheme_file = {
+ "file", /* scheme */
+#ifdef CURL_DISABLE_FILE
+ ZERO_NULL,
+#else
+ &Curl_protocol_file,
+#endif
+ CURLPROTO_FILE, /* protocol */
+ CURLPROTO_FILE, /* family */
+ PROTOPT_NONETWORK | PROTOPT_NOURLQUERY, /* flags */
+ 0 /* defport */
+};
diff --git a/Utilities/cmcurl/lib/file.h b/Utilities/cmcurl/lib/file.h
index cb3552d..a306544 100644
--- a/Utilities/cmcurl/lib/file.h
+++ b/Utilities/cmcurl/lib/file.h
@@ -23,8 +23,6 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#ifndef CURL_DISABLE_FILE
-extern const struct Curl_handler Curl_handler_file;
-#endif
+extern const struct Curl_scheme Curl_scheme_file;
#endif /* HEADER_CURL_FILE_H */
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 8c4dc48..3770d28 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -31,7 +31,7 @@
#include "urldata.h" /* for struct Curl_easy */
#include "mime.h"
-#include "strdup.h"
+#include "curlx/strdup.h"
#include "bufref.h"
#include "curlx/fopen.h"
@@ -168,10 +168,9 @@
*
* Stores a formpost parameter and builds the appropriate linked list.
*
- * Has two principal functionalities: using files and byte arrays as
- * post parts. Byte arrays are either copied or just the pointer is stored
- * (as the user requests) while for files only the filename and not the
- * content is stored.
+ * Has two principal functionalities: using files and byte arrays as post
+ * parts. Byte arrays are either copied or the pointer is stored (as the user
+ * requests) while for files only the filename and not the content is stored.
*
* While you may have only one byte array for each name, multiple filenames
* are allowed (and because of this feature CURLFORM_END is needed after
@@ -304,13 +303,13 @@
struct FormInfo *first_form, *curr, *form = NULL;
CURLFORMcode retval = CURL_FORMADD_OK;
CURLformoption option;
- struct curl_forms *forms = NULL;
+ const struct curl_forms *forms = NULL;
char *avalue = NULL;
struct curl_httppost *newchain = NULL;
struct curl_httppost *lastnode = NULL;
#define form_ptr_arg(t) (forms ? (t)(void *)avalue : va_arg(params, t))
-#ifdef HAVE_STDINT_H
+#ifdef HAVE_UINTPTR_T
#define form_int_arg(t) (forms ? (t)(uintptr_t)avalue : va_arg(params, t))
#else
#define form_int_arg(t) (forms ? (t)(void *)avalue : va_arg(params, t))
@@ -667,7 +666,7 @@
struct curl_httppost *next;
if(!form)
- /* no form to free, just get out of this */
+ /* no form to free, get out of this */
return;
do {
@@ -696,7 +695,7 @@
if(!name || !len)
return curl_mime_name(part, name);
- zname = Curl_memdup0(name, len);
+ zname = curlx_memdup0(name, len);
if(!zname)
return CURLE_OUT_OF_MEMORY;
res = curl_mime_name(part, zname);
@@ -710,8 +709,8 @@
* mime part at '*finalform'.
*
* This function will not do a failf() for the potential memory failures but
- * should for all other errors it spots. Just note that this function MAY get
- * a NULL pointer in the 'data' argument.
+ * should for all other errors it spots. Note that this function MAY get a
+ * NULL pointer in the 'data' argument.
*/
CURLcode Curl_getformdata(CURL *data,
@@ -840,8 +839,7 @@
return result;
}
-#else
-/* if disabled */
+#else /* if disabled */
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post, ...)
{
diff --git a/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h
index ce592a8..33d7d0a 100644
--- a/Utilities/cmcurl/lib/formdata.h
+++ b/Utilities/cmcurl/lib/formdata.h
@@ -47,7 +47,7 @@
};
CURLcode Curl_getformdata(CURL *data,
- curl_mimepart *,
+ curl_mimepart *finalform,
struct curl_httppost *post,
curl_read_callback fread_func);
#endif /* CURL_DISABLE_FORM_API */
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 9c3beda..5b1151e 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -22,6 +22,7 @@
*
***************************************************************************/
#include "curl_setup.h"
+#include "urldata.h"
#ifndef CURL_DISABLE_FTP
@@ -39,8 +40,8 @@
#include <inet.h>
#endif
-#include "urldata.h"
#include "sendf.h"
+#include "curl_addrinfo.h"
#include "curl_trc.h"
#include "if2ip.h"
#include "hostip.h"
@@ -48,7 +49,6 @@
#include "transfer.h"